mirror of
https://github.com/1024-lab/smart-admin.git
synced 2026-06-26 23:54:23 +00:00
【V3.5.0】1、【新增】轻量级定时任务 SmartJob;2、【新增】站内信;3、【新增】个人中心;4、【新增】岗位管理;5、【优化】部门员工管理
This commit is contained in:
+157
@@ -0,0 +1,157 @@
|
||||
<!--
|
||||
* 角色 数据范围
|
||||
*
|
||||
* @Author: 1024创新实验室-主任:卓大
|
||||
* @Date: 2022-09-12 22:34:00
|
||||
* @Wechat: zhuda1024
|
||||
* @Email: lab1024@163.com
|
||||
* @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012
|
||||
*
|
||||
-->
|
||||
<template>
|
||||
<div>
|
||||
<div class="btn-group">
|
||||
<a-button class="button-style" type="primary" @click="updateDataScope" v-privilege="'system:role:dataScope:update'"> 保存 </a-button>
|
||||
<a-button class="button-style" @click="getDataScope"> 刷新 </a-button>
|
||||
</div>
|
||||
<a-row class="header">
|
||||
<a-col class="tab-margin" :span="4">业务单据</a-col>
|
||||
<a-col class="tab-data" :span="8">查看数据范围</a-col>
|
||||
<a-col class="tab-margin" :span="12" />
|
||||
</a-row>
|
||||
<div class="data-container">
|
||||
<a-row class="data" align="middle" justify="center" v-for="(item, index) in dataScopeList" :key="item.dataScopeType">
|
||||
<a-col class="tab-margin" :span="4">
|
||||
{{ item.dataScopeTypeName }}
|
||||
</a-col>
|
||||
<a-col class="tab-data" :span="8">
|
||||
<a-radio-group v-model:value="selectedDataScopeList[index].viewType">
|
||||
<a-radio
|
||||
v-for="scope in item.viewTypeList"
|
||||
:key="`${item.dataScopeType}-${scope.viewType}`"
|
||||
class="radio-style"
|
||||
:value="scope.viewType"
|
||||
>{{ scope.viewTypeName }}</a-radio
|
||||
>
|
||||
</a-radio-group>
|
||||
</a-col>
|
||||
<a-col class="tab-margin tab-desc" :span="12">
|
||||
<p>{{ item.dataScopeTypeDesc }}</p>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { message } from 'ant-design-vue';
|
||||
import _ from 'lodash';
|
||||
import { inject, onMounted, ref, watch } from 'vue';
|
||||
import { roleApi } from '/src/api/system/role-api';
|
||||
import { smartSentry } from '/src/lib/smart-sentry';
|
||||
|
||||
const props = defineProps({
|
||||
value: Number,
|
||||
});
|
||||
|
||||
defineEmits(['update:value']);
|
||||
|
||||
// ----------------------- 显示 ---------------------------------
|
||||
|
||||
let selectRoleId = inject('selectRoleId');
|
||||
let dataScopeList = ref([]);
|
||||
let selectedDataScopeList = ref([]);
|
||||
|
||||
watch(
|
||||
() => selectRoleId.value,
|
||||
() => getRoleDataScope()
|
||||
);
|
||||
|
||||
onMounted(getDataScope);
|
||||
|
||||
// 获取系统支持的所有种类的数据范围
|
||||
async function getDataScope() {
|
||||
let result = await roleApi.getDataScopeList();
|
||||
dataScopeList.value = result.data;
|
||||
|
||||
selectedDataScopeList.value = [];
|
||||
|
||||
dataScopeList.value.forEach((item) => {
|
||||
selectedDataScopeList.value.push({
|
||||
viewType: undefined,
|
||||
dataScopeType: item.dataScopeType,
|
||||
});
|
||||
});
|
||||
getRoleDataScope();
|
||||
}
|
||||
|
||||
// 获取数据范围根据角色id,并赋予选中状态
|
||||
async function getRoleDataScope() {
|
||||
let result = await roleApi.getDataScopeByRoleId(selectRoleId.value);
|
||||
let data = result.data;
|
||||
selectedDataScopeList.value = [];
|
||||
|
||||
dataScopeList.value.forEach((item) => {
|
||||
let find = data.find((e) => e.dataScopeType == item.dataScopeType);
|
||||
selectedDataScopeList.value.push({
|
||||
viewType: find ? find.viewType : undefined,
|
||||
dataScopeType: item.dataScopeType,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// ----------------------- 数据范围更新 ---------------------------------
|
||||
// 更新
|
||||
async function updateDataScope() {
|
||||
try {
|
||||
let data = {
|
||||
roleId: selectRoleId.value,
|
||||
dataScopeItemList: selectedDataScopeList.value.filter((e) => !_.isUndefined(e.viewType)),
|
||||
};
|
||||
await roleApi.updateDataScope(data);
|
||||
message.success('保存成功');
|
||||
getDataScope();
|
||||
} catch (e) {
|
||||
smartSentry.captureError(e);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="less">
|
||||
.btn-group {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.button-style {
|
||||
margin: 0 10px;
|
||||
}
|
||||
.header {
|
||||
border-bottom: 1px solid #f2f2f2;
|
||||
font-weight: 600;
|
||||
margin: 10px 0px;
|
||||
}
|
||||
.tab-data {
|
||||
margin: 10px 0px;
|
||||
}
|
||||
|
||||
.data-container {
|
||||
height: 680px;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
.data {
|
||||
border-bottom: 1px solid #f2f2f2;
|
||||
margin: 10px 0px;
|
||||
}
|
||||
.radio-style {
|
||||
display: block;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
}
|
||||
.tab-margin {
|
||||
text-align: center;
|
||||
margin: 10px 0px;
|
||||
}
|
||||
.tab-desc {
|
||||
line-height: 30px;
|
||||
font-size: 16px;
|
||||
text-align: left;
|
||||
}
|
||||
</style>
|
||||
+274
@@ -0,0 +1,274 @@
|
||||
<!--
|
||||
* 角色 员工 列表
|
||||
*
|
||||
* @Author: 1024创新实验室-主任:卓大
|
||||
* @Date: 2022-09-12 22:34:00
|
||||
* @Wechat: zhuda1024
|
||||
* @Email: lab1024@163.com
|
||||
* @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012
|
||||
*
|
||||
-->
|
||||
<template>
|
||||
<div>
|
||||
<div class="header">
|
||||
<div>
|
||||
关键字:
|
||||
<a-input style="width: 250px" v-model:value="queryForm.keywords" placeholder="姓名/手机号/登录账号" />
|
||||
<a-button class="button-style" v-if="selectRoleId" type="primary" @click="onSearch">搜索</a-button>
|
||||
<a-button class="button-style" v-if="selectRoleId" type="default" @click="resetQueryRoleEmployee">重置</a-button>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<a-button class="button-style" v-if="selectRoleId" type="primary" @click="addRoleEmployee" v-privilege="'system:role:employee:add'"
|
||||
>添加员工</a-button
|
||||
>
|
||||
<a-button
|
||||
class="button-style"
|
||||
v-if="selectRoleId"
|
||||
type="primary"
|
||||
danger
|
||||
@click="batchDelete"
|
||||
v-privilege="'system:role:employee:batch:delete'"
|
||||
>批量移除</a-button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<a-table
|
||||
:loading="tableLoading"
|
||||
:dataSource="tableData"
|
||||
:columns="columns"
|
||||
:pagination="false"
|
||||
:scroll="{ y: 400 }"
|
||||
rowKey="employeeId"
|
||||
:row-selection="{ selectedRowKeys: selectedRowKeyList, onChange: onSelectChange }"
|
||||
size="small"
|
||||
bordered
|
||||
>
|
||||
<template #bodyCell="{ text, record, column }">
|
||||
<template v-if="column.dataIndex === 'disabledFlag'">
|
||||
<a-tag :color="text ? 'error' : 'processing'">{{ text ? '禁用' : '启用' }}</a-tag>
|
||||
</template>
|
||||
<template v-else-if="column.dataIndex === 'gender'">
|
||||
<span>{{ $smartEnumPlugin.getDescByValue('GENDER_ENUM', text) }}</span>
|
||||
</template>
|
||||
<template v-if="column.dataIndex === 'operate'">
|
||||
<a @click="deleteEmployeeRole(record.employeeId)" v-privilege="'system:role:employee:delete'">移除</a>
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
<div class="smart-query-table-page">
|
||||
<a-pagination
|
||||
showSizeChanger
|
||||
showQuickJumper
|
||||
show-less-items
|
||||
:pageSizeOptions="PAGE_SIZE_OPTIONS"
|
||||
:defaultPageSize="queryForm.pageSize"
|
||||
v-model:current="queryForm.pageNum"
|
||||
v-model:pageSize="queryForm.pageSize"
|
||||
:total="total"
|
||||
@change="queryRoleEmployee"
|
||||
@showSizeChange="queryRoleEmployee"
|
||||
:show-total="showTableTotal"
|
||||
/>
|
||||
</div>
|
||||
<EmployeeTableSelectModal ref="selectEmployeeModal" @selectData="selectData" />
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { message, Modal } from 'ant-design-vue';
|
||||
import _ from 'lodash';
|
||||
import { computed, inject, onMounted, reactive, ref, watch } from 'vue';
|
||||
import { roleApi } from '/src/api/system/role-api';
|
||||
import { PAGE_SIZE, showTableTotal, PAGE_SIZE_OPTIONS } from '/src/constants/common-const';
|
||||
import { SmartLoading } from '/src/components/framework/smart-loading';
|
||||
import EmployeeTableSelectModal from '/src/components/system/employee-table-select-modal/index.vue';
|
||||
import { smartSentry } from '/src/lib/smart-sentry';
|
||||
|
||||
// ----------------------- 以下是字段定义 emits props ---------------------
|
||||
let selectRoleId = inject('selectRoleId');
|
||||
|
||||
// ----------------------- 员工列表:显示和搜索 ------------------------
|
||||
watch(
|
||||
() => selectRoleId.value,
|
||||
() => queryRoleEmployee()
|
||||
);
|
||||
|
||||
onMounted(queryRoleEmployee);
|
||||
|
||||
const defaultQueryForm = {
|
||||
pageNum: 1,
|
||||
pageSize: PAGE_SIZE,
|
||||
roleId: undefined,
|
||||
keywords: undefined,
|
||||
};
|
||||
// 查询表单
|
||||
const queryForm = reactive({ ...defaultQueryForm });
|
||||
// 总数
|
||||
const total = ref(0);
|
||||
// 表格数据
|
||||
const tableData = ref([]);
|
||||
// 表格loading效果
|
||||
const tableLoading = ref(false);
|
||||
|
||||
function resetQueryRoleEmployee() {
|
||||
queryForm.keywords = '';
|
||||
queryRoleEmployee();
|
||||
}
|
||||
|
||||
function onSearch() {
|
||||
queryForm.pageNum = 1;
|
||||
queryRoleEmployee();
|
||||
}
|
||||
|
||||
async function queryRoleEmployee() {
|
||||
try {
|
||||
tableLoading.value = true;
|
||||
queryForm.roleId = selectRoleId.value;
|
||||
let res = await roleApi.queryRoleEmployee(queryForm);
|
||||
tableData.value = res.data.list;
|
||||
total.value = res.data.total;
|
||||
} catch (e) {
|
||||
smartSentry.captureError(e);
|
||||
} finally {
|
||||
tableLoading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
const columns = reactive([
|
||||
{
|
||||
title: '姓名',
|
||||
dataIndex: 'actualName',
|
||||
},
|
||||
{
|
||||
title: '手机号',
|
||||
dataIndex: 'phone',
|
||||
},
|
||||
{
|
||||
title: '登录账号',
|
||||
dataIndex: 'loginName',
|
||||
},
|
||||
{
|
||||
title: '部门',
|
||||
dataIndex: 'departmentName',
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
dataIndex: 'disabledFlag',
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
dataIndex: 'operate',
|
||||
width: 60,
|
||||
},
|
||||
]);
|
||||
|
||||
// ----------------------- 添加成员 ---------------------------------
|
||||
const selectEmployeeModal = ref();
|
||||
|
||||
async function addRoleEmployee() {
|
||||
let res = await roleApi.getRoleAllEmployee(selectRoleId.value);
|
||||
let selectedIdList = res.data.map((e) => e.roleId) || [];
|
||||
selectEmployeeModal.value.showModal(selectedIdList);
|
||||
}
|
||||
|
||||
async function selectData(list) {
|
||||
if (_.isEmpty(list)) {
|
||||
message.warning('请选择角色人员');
|
||||
return;
|
||||
}
|
||||
SmartLoading.show();
|
||||
try {
|
||||
let params = {
|
||||
employeeIdList: list,
|
||||
roleId: selectRoleId.value,
|
||||
};
|
||||
await roleApi.batchAddRoleEmployee(params);
|
||||
message.success('添加成功');
|
||||
await queryRoleEmployee();
|
||||
} catch (e) {
|
||||
smartSentry.captureError(e);
|
||||
} finally {
|
||||
SmartLoading.hide();
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------- 移除成员 ---------------------------------
|
||||
// 删除角色成员方法
|
||||
async function deleteEmployeeRole(employeeId) {
|
||||
Modal.confirm({
|
||||
title: '提示',
|
||||
content: '确定要删除该角色成员么?',
|
||||
okText: '确定',
|
||||
okType: 'danger',
|
||||
async onOk() {
|
||||
SmartLoading.show();
|
||||
try {
|
||||
await roleApi.deleteEmployeeRole(employeeId, selectRoleId.value);
|
||||
message.success('移除成功');
|
||||
await queryRoleEmployee();
|
||||
} catch (e) {
|
||||
smartSentry.captureError(e);
|
||||
} finally {
|
||||
SmartLoading.hide();
|
||||
}
|
||||
},
|
||||
cancelText: '取消',
|
||||
onCancel() {},
|
||||
});
|
||||
}
|
||||
|
||||
// ----------------------- 批量删除 ---------------------------------
|
||||
|
||||
const selectedRowKeyList = ref([]);
|
||||
const hasSelected = computed(() => selectedRowKeyList.value.length > 0);
|
||||
|
||||
function onSelectChange(selectedRowKeys) {
|
||||
selectedRowKeyList.value = selectedRowKeys;
|
||||
}
|
||||
|
||||
// 批量移除
|
||||
function batchDelete() {
|
||||
if (!hasSelected.value) {
|
||||
message.warning('请选择要删除的角色成员');
|
||||
return;
|
||||
}
|
||||
Modal.confirm({
|
||||
title: '提示',
|
||||
content: '确定移除这些角色成员吗?',
|
||||
okText: '确定',
|
||||
okType: 'danger',
|
||||
async onOk() {
|
||||
SmartLoading.show();
|
||||
try {
|
||||
let params = {
|
||||
employeeIdList: selectedRowKeyList.value,
|
||||
roleId: selectRoleId.value,
|
||||
};
|
||||
await roleApi.batchRemoveRoleEmployee(params);
|
||||
message.success('移除成功');
|
||||
selectedRowKeyList.value = [];
|
||||
await queryRoleEmployee();
|
||||
} catch (e) {
|
||||
smartSentry.captureError(e);
|
||||
} finally {
|
||||
SmartLoading.hide();
|
||||
}
|
||||
},
|
||||
cancelText: '取消',
|
||||
onCancel() {},
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
.header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin: 20px 0;
|
||||
}
|
||||
.button-style {
|
||||
margin: 0 10px;
|
||||
}
|
||||
</style>
|
||||
+116
@@ -0,0 +1,116 @@
|
||||
<!--
|
||||
* 角色 表单
|
||||
*
|
||||
* @Author: 1024创新实验室-主任:卓大
|
||||
* @Date: 2022-09-12 22:34:00
|
||||
* @Wechat: zhuda1024
|
||||
* @Email: lab1024@163.com
|
||||
* @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012
|
||||
*
|
||||
-->
|
||||
<template>
|
||||
<a-modal :title="form.roleId ? '编辑角色' : '添加角色'" :width="600" :open="modalVisible" @cancel="onClose" :footer="null">
|
||||
<a-form ref="formRef" :model="form" :rules="rules" :labelCol="{ span: 4 }">
|
||||
<a-form-item label="角色名称" name="roleName">
|
||||
<a-input style="width: 100%" placeholder="请输入角色名称" v-model:value="form.roleName" />
|
||||
</a-form-item>
|
||||
<a-form-item label="角色编码" name="roleCode">
|
||||
<a-input style="width: 100%" placeholder="请输入角色编码" v-model:value="form.roleCode" />
|
||||
</a-form-item>
|
||||
<a-form-item label="角色备注">
|
||||
<a-input style="width: 100%" placeholder="请输入角色备注" v-model:value="form.remark" />
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
|
||||
<div class="footer">
|
||||
<a-button style="margin-right: 8px" @click="onClose">取消</a-button>
|
||||
<a-button type="primary" @click="submitForm">提交</a-button>
|
||||
</div>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { message } from 'ant-design-vue';
|
||||
import { reactive, ref } from 'vue';
|
||||
import { roleApi } from '/src/api/system/role-api';
|
||||
import { smartSentry } from '/src/lib/smart-sentry';
|
||||
import { SmartLoading } from '/src/components/framework/smart-loading';
|
||||
// ----------------------- 以下是字段定义 emits props ---------------------
|
||||
let emits = defineEmits(['refresh']);
|
||||
|
||||
defineExpose({
|
||||
showModal,
|
||||
});
|
||||
|
||||
// ----------------------- modal 显示与隐藏 ---------------------
|
||||
const modalVisible = ref(false);
|
||||
|
||||
function showModal(role) {
|
||||
Object.assign(form, formDefault);
|
||||
if (role) {
|
||||
Object.assign(form, role);
|
||||
}
|
||||
modalVisible.value = true;
|
||||
}
|
||||
|
||||
function onClose() {
|
||||
Object.assign(form, formDefault);
|
||||
modalVisible.value = false;
|
||||
}
|
||||
|
||||
// ----------------------- 表单 ---------------------
|
||||
|
||||
const formRef = ref();
|
||||
|
||||
const formDefault = {
|
||||
roleId: undefined,
|
||||
remark: undefined,
|
||||
roleCode: undefined,
|
||||
roleName: undefined,
|
||||
};
|
||||
|
||||
let form = reactive({ ...formDefault });
|
||||
|
||||
// 表单规则
|
||||
const rules = {
|
||||
roleName: [{ required: true, message: '请输入角色名称' }],
|
||||
roleCode: [{ required: true, message: '请输入角色编码' }],
|
||||
};
|
||||
|
||||
// 提交表单
|
||||
async function submitForm() {
|
||||
formRef.value
|
||||
.validate()
|
||||
.then(async () => {
|
||||
SmartLoading.show();
|
||||
try {
|
||||
if (form.roleId) {
|
||||
await roleApi.updateRole(form);
|
||||
} else {
|
||||
await roleApi.addRole(form);
|
||||
}
|
||||
message.info(`${form.roleId ? '编辑' : '添加'}成功`);
|
||||
emits('refresh');
|
||||
onClose();
|
||||
} catch (e) {
|
||||
smartSentry.captureError(e);
|
||||
} finally {
|
||||
SmartLoading.hide();
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
message.error('参数验证错误,请仔细填写表单数据!');
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
.footer {
|
||||
width: 100%;
|
||||
border-top: 1px solid #e9e9e9;
|
||||
padding: 10px 16px;
|
||||
background: #fff;
|
||||
text-align: right;
|
||||
z-index: 1;
|
||||
}
|
||||
</style>
|
||||
+116
@@ -0,0 +1,116 @@
|
||||
<!--
|
||||
* 角色 列表
|
||||
*
|
||||
* @Author: 1024创新实验室-主任:卓大
|
||||
* @Date: 2022-09-12 22:34:00
|
||||
* @Wechat: zhuda1024
|
||||
* @Email: lab1024@163.com
|
||||
* @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012
|
||||
*
|
||||
-->
|
||||
<template>
|
||||
<a-card title="角色列表" class="role-container" style="padding: 0">
|
||||
<template #extra>
|
||||
<a-button type="primary" size="small" @click="showRoleFormModal" v-privilege="'system:role:add'">添加</a-button>
|
||||
</template>
|
||||
<a-menu mode="vertical" v-model:selectedKeys="selectedKeys">
|
||||
<a-menu-item v-for="item in roleList" :key="item.roleId">
|
||||
<a-popover placement="right">
|
||||
<template #content>
|
||||
<div style="display: flex; flex-direction: column">
|
||||
<a-button type="text" @click="deleteRole(item.roleId)" v-privilege="'system:role:delete'">删除</a-button>
|
||||
<a-button type="text" @click="showRoleFormModal(item)" v-privilege="'system:role:update'">编辑</a-button>
|
||||
</div>
|
||||
</template>
|
||||
{{ item.roleName }}
|
||||
</a-popover>
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</a-card>
|
||||
<RoleFormModal ref="roleFormModal" @refresh="queryAllRole" />
|
||||
</template>
|
||||
<script setup>
|
||||
import { message, Modal } from 'ant-design-vue';
|
||||
import _ from 'lodash';
|
||||
import { computed, onMounted, ref } from 'vue';
|
||||
import { roleApi } from '/src/api/system/role-api';
|
||||
import { SmartLoading } from '/src/components/framework/smart-loading';
|
||||
import RoleFormModal from '../role-form-modal/index.vue';
|
||||
import { smartSentry } from '/src/lib/smart-sentry';
|
||||
|
||||
// ----------------------- 角色列表显示 ---------------------
|
||||
const roleList = ref([]);
|
||||
|
||||
onMounted(queryAllRole);
|
||||
|
||||
// 查询列表
|
||||
async function queryAllRole() {
|
||||
let res = await roleApi.queryAll();
|
||||
roleList.value = res.data;
|
||||
if (!_.isEmpty(res.data) && res.data[0].roleId) {
|
||||
selectedKeys.value = [res.data[0].roleId];
|
||||
}
|
||||
}
|
||||
|
||||
let selectedKeys = ref([]);
|
||||
const selectRoleId = computed(() => {
|
||||
if (!selectedKeys.value && _.isEmpty(selectedKeys.value)) {
|
||||
return null;
|
||||
}
|
||||
return selectedKeys.value[0];
|
||||
});
|
||||
// ----------------------- 添加、修改、删除 ---------------------------------
|
||||
const roleFormModal = ref();
|
||||
|
||||
// 显示表单框
|
||||
function showRoleFormModal(role) {
|
||||
roleFormModal.value.showModal(role);
|
||||
}
|
||||
|
||||
// 删除角色
|
||||
function deleteRole(roleId) {
|
||||
if (!roleId) {
|
||||
return;
|
||||
}
|
||||
Modal.confirm({
|
||||
title: '提示',
|
||||
content: '确定要删除该角色么?',
|
||||
okText: '确定',
|
||||
okType: 'danger',
|
||||
async onOk() {
|
||||
SmartLoading.show();
|
||||
try {
|
||||
await roleApi.deleteRole(roleId);
|
||||
message.info('删除成功');
|
||||
queryAllRole();
|
||||
} catch (e) {
|
||||
smartSentry.captureError(e);
|
||||
} finally {
|
||||
SmartLoading.hide();
|
||||
}
|
||||
},
|
||||
cancelText: '取消',
|
||||
onCancel() {},
|
||||
});
|
||||
}
|
||||
|
||||
// ----------------------- 以下是暴露的方法内容 ----------------------------
|
||||
defineExpose({
|
||||
selectRoleId,
|
||||
});
|
||||
</script>
|
||||
<style scoped lang="less">
|
||||
.role-container {
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
|
||||
:deep(.ant-card-body) {
|
||||
padding: 5px;
|
||||
}
|
||||
}
|
||||
.ant-menu-inline,
|
||||
.ant-menu-vertical,
|
||||
.ant-menu-vertical-left {
|
||||
border-right: none;
|
||||
}
|
||||
</style>
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
<!--
|
||||
* 角色 设置
|
||||
*
|
||||
* @Author: 1024创新实验室-主任:卓大
|
||||
* @Date: 2022-09-12 22:34:00
|
||||
* @Wechat: zhuda1024
|
||||
* @Email: lab1024@163.com
|
||||
* @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012
|
||||
*
|
||||
-->
|
||||
<template>
|
||||
<a-card class="role-container">
|
||||
<a-tabs v-model:activeKey="activeKey">
|
||||
<a-tab-pane key="1" tab="角色-功能权限">
|
||||
<RoleTree />
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="2" tab="角色-数据范围">
|
||||
<RoleDataScope />
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="3" tab="角色-员工列表">
|
||||
<RoleEmployeeList />
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
</a-card>
|
||||
</template>
|
||||
<script setup>
|
||||
import { ref } from 'vue';
|
||||
import RoleDataScope from '../role-data-scope/index.vue';
|
||||
import RoleEmployeeList from '../role-employee-list/index.vue';
|
||||
import RoleTree from '../role-tree/index.vue';
|
||||
|
||||
defineProps({
|
||||
value: Number,
|
||||
});
|
||||
|
||||
defineEmits(['update:value']);
|
||||
|
||||
let activeKey = ref();
|
||||
</script>
|
||||
<style scoped lang="less">
|
||||
.role-container {
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
:deep(.ant-checkbox-group) {
|
||||
width: 100%;
|
||||
}
|
||||
.tree-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin: 20px 0;
|
||||
}
|
||||
.col-desc {
|
||||
margin: 20px 0;
|
||||
font-size: 15px;
|
||||
color: #95a5a6;
|
||||
padding: 0 20px;
|
||||
}
|
||||
.button-style {
|
||||
margin: 20px 0 20px 0;
|
||||
padding-left: 20px;
|
||||
text-align: right;
|
||||
}
|
||||
.check-right {
|
||||
margin-right: 20px;
|
||||
}
|
||||
.row-border {
|
||||
border: 1px solid #f0f0f0;
|
||||
}
|
||||
.col-border {
|
||||
line-height: 50px;
|
||||
padding-left: 20px;
|
||||
border-right: 1px solid #f0f0f0;
|
||||
}
|
||||
.col-left {
|
||||
line-height: 50px;
|
||||
padding-left: 40px;
|
||||
border-right: 1px solid #f0f0f0;
|
||||
}
|
||||
.col-right {
|
||||
padding-left: 20px;
|
||||
border-right: 1px solid #f0f0f0;
|
||||
}
|
||||
.checked-box {
|
||||
padding: 0 15px;
|
||||
:deep(ul li::marker) {
|
||||
content: '';
|
||||
}
|
||||
:deep(ul) {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
|
||||
li {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 10px 0;
|
||||
|
||||
.menu {
|
||||
border-bottom: 1px solid rgb(240, 240, 240);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
line-height: 25px;
|
||||
}
|
||||
|
||||
.point {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.point-label {
|
||||
flex: 1;
|
||||
padding-left: 40px;
|
||||
border-left: 1px rgb(240, 240, 240) solid;
|
||||
}
|
||||
}
|
||||
|
||||
.checked-box-label {
|
||||
min-width: 150px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
<!--
|
||||
* 角色 树形结构
|
||||
*
|
||||
* @Author: 1024创新实验室-主任:卓大
|
||||
* @Date: 2022-09-12 22:34:00
|
||||
* @Wechat: zhuda1024
|
||||
* @Email: lab1024@163.com
|
||||
* @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012
|
||||
*
|
||||
-->
|
||||
<template>
|
||||
<div>
|
||||
<div class="tree-header">
|
||||
<p>设置角色对应的功能操作、后台管理权限</p>
|
||||
<a-button v-if="selectRoleId" type="primary" @click="saveChange" v-privilege="'system:role:menu:update'"> 保存 </a-button>
|
||||
</div>
|
||||
<!-- 功能权限勾选部分 -->
|
||||
<RoleTreeCheckbox :tree="tree" />
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { inject, ref, watch } from 'vue';
|
||||
import { message } from 'ant-design-vue';
|
||||
import _ from 'lodash';
|
||||
import RoleTreeCheckbox from './role-tree-checkbox.vue';
|
||||
import { roleMenuApi } from '/src/api/system/role-menu-api';
|
||||
import { useRoleStore } from '/src/store/modules/system/role';
|
||||
import { SmartLoading } from '/src/components/framework/smart-loading';
|
||||
import { smartSentry } from '/src/lib/smart-sentry';
|
||||
|
||||
let roleStore = useRoleStore();
|
||||
let tree = ref();
|
||||
let selectRoleId = inject('selectRoleId');
|
||||
|
||||
watch(selectRoleId, () => getRoleSelectedMenu(), {
|
||||
immediate: true,
|
||||
});
|
||||
|
||||
async function getRoleSelectedMenu() {
|
||||
if (!selectRoleId.value) {
|
||||
return;
|
||||
}
|
||||
let res = await roleMenuApi.getRoleSelectedMenu(selectRoleId.value);
|
||||
let data = res.data;
|
||||
if (_.isEmpty(roleStore.treeMap)) {
|
||||
roleStore.initTreeMap(data.menuTreeList || []);
|
||||
}
|
||||
roleStore.initCheckedData(data.selectedMenuId || []);
|
||||
tree.value = data.menuTreeList;
|
||||
}
|
||||
async function saveChange() {
|
||||
let checkedData = roleStore.checkedData;
|
||||
if (_.isEmpty(checkedData)) {
|
||||
message.error('还未选择任何权限');
|
||||
return;
|
||||
}
|
||||
let params = {
|
||||
roleId: selectRoleId.value,
|
||||
menuIdList: checkedData,
|
||||
};
|
||||
SmartLoading.show();
|
||||
try {
|
||||
await roleMenuApi.updateRoleMenu(params);
|
||||
message.success('保存成功');
|
||||
} catch (error) {
|
||||
smartSentry.captureError(error);
|
||||
} finally {
|
||||
SmartLoading.hide();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="less">
|
||||
@import 'index.less';
|
||||
</style>
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
<!--
|
||||
* 角色
|
||||
*
|
||||
* @Author: 1024创新实验室-主任:卓大
|
||||
* @Date: 2022-09-12 22:34:00
|
||||
* @Wechat: zhuda1024
|
||||
* @Email: lab1024@163.com
|
||||
* @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012
|
||||
*
|
||||
-->
|
||||
<template>
|
||||
<div style="overflow: auto">
|
||||
<a-checkbox-group v-model:value="checkedData">
|
||||
<div class="checked-box">
|
||||
<ul>
|
||||
<!--li 菜单模块 start-->
|
||||
<RoleTreeMenu :tree="props.tree" :index="0" />
|
||||
<!--li 菜单模块 end-->
|
||||
</ul>
|
||||
</div>
|
||||
</a-checkbox-group>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { ref, watch } from 'vue';
|
||||
import { useRoleStore } from '/src/store/modules/system/role';
|
||||
import RoleTreeMenu from './role-tree-menu.vue';
|
||||
|
||||
let props = defineProps({
|
||||
tree: {
|
||||
type: Array,
|
||||
default: [],
|
||||
},
|
||||
});
|
||||
defineEmits(['update:value']);
|
||||
|
||||
let roleStore = useRoleStore();
|
||||
let checkedData = ref();
|
||||
watch(
|
||||
() => roleStore.checkedData,
|
||||
(e) => (checkedData.value = e),
|
||||
{
|
||||
deep: true,
|
||||
}
|
||||
);
|
||||
</script>
|
||||
<style scoped lang="less">
|
||||
@import 'index.less';
|
||||
</style>
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
<!--
|
||||
* 角色 菜单
|
||||
*
|
||||
* @Author: 1024创新实验室-主任:卓大
|
||||
* @Date: 2022-09-12 22:34:00
|
||||
* @Wechat: zhuda1024
|
||||
* @Email: lab1024@163.com
|
||||
* @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012
|
||||
*
|
||||
-->
|
||||
<template>
|
||||
<li v-for="module in props.tree" :key="module.menuId">
|
||||
<div class="menu" :style="{ marginLeft: `${props.index * 4}%` }">
|
||||
<a-checkbox @change="selectCheckbox(module)" class="checked-box-label" :value="module.menuId">{{ module.menuName }} </a-checkbox>
|
||||
<div v-if="module.children && module.children.some((e) => e.menuType == MENU_TYPE_ENUM.POINTS.value)">
|
||||
<RoleTreePoint :tree="module.children" @selectCheckbox="selectCheckbox" />
|
||||
</div>
|
||||
</div>
|
||||
<template v-if="module.children && !module.children.some((e) => e.menuType == MENU_TYPE_ENUM.POINTS.value)">
|
||||
<RoleTreeMenu :tree="module.children" :index="props.index + 1" />
|
||||
</template>
|
||||
</li>
|
||||
</template>
|
||||
<script setup>
|
||||
import { MENU_TYPE_ENUM } from '/src/constants/system/menu-const';
|
||||
import { useRoleStore } from '/src/store/modules/system/role';
|
||||
import RoleTreePoint from './role-tree-point.vue';
|
||||
import RoleTreeMenu from './role-tree-menu.vue';
|
||||
|
||||
const props = defineProps({
|
||||
tree: {
|
||||
type: Array,
|
||||
default: [],
|
||||
},
|
||||
index: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
});
|
||||
defineEmits(['update:value']);
|
||||
let roleStore = useRoleStore();
|
||||
function selectCheckbox(module) {
|
||||
if (!module.menuId) {
|
||||
return;
|
||||
}
|
||||
// 是否勾选
|
||||
let checkedData = roleStore.checkedData;
|
||||
let findIndex = checkedData.indexOf(module.menuId);
|
||||
// 选中
|
||||
if (findIndex == -1) {
|
||||
// 选中本级以及子级
|
||||
roleStore.addCheckedDataAndChildren(module);
|
||||
// 选中上级
|
||||
roleStore.selectUpperLevel(module);
|
||||
// 是否有关联菜单 有则选中
|
||||
if (module.contextMenuId) {
|
||||
roleStore.addCheckedData(module.contextMenuId);
|
||||
}
|
||||
} else {
|
||||
// 取消选中本级以及子级
|
||||
roleStore.deleteCheckedDataAndChildren(module);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
<!--
|
||||
* 角色 功能点
|
||||
*
|
||||
* @Author: 1024创新实验室-主任:卓大
|
||||
* @Date: 2022-09-12 22:34:00
|
||||
* @Wechat: zhuda1024
|
||||
* @Email: lab1024@163.com
|
||||
* @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012
|
||||
*
|
||||
-->
|
||||
<template>
|
||||
<div class="point">
|
||||
<div class="point-label">
|
||||
<template v-for="module in props.tree" :key="module.menuId">
|
||||
<a-checkbox @change="emits('selectCheckbox', module)" :value="module.menuId">{{ module.menuName }} </a-checkbox>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
const props = defineProps({
|
||||
tree: {
|
||||
type: Array,
|
||||
default: [],
|
||||
},
|
||||
index: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
});
|
||||
let emits = defineEmits(['selectCheckbox']);
|
||||
</script>
|
||||
<style scoped lang="less"></style>
|
||||
@@ -0,0 +1,48 @@
|
||||
<!--
|
||||
* 角色 管理
|
||||
*
|
||||
* @Author: 1024创新实验室-主任:卓大
|
||||
* @Date: 2022-09-12 22:34:00
|
||||
* @Wechat: zhuda1024
|
||||
* @Email: lab1024@163.com
|
||||
* @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012
|
||||
*
|
||||
-->
|
||||
<template>
|
||||
<div class="height100">
|
||||
<a-row :gutter="10" type="flex" class="height100">
|
||||
<a-col flex="200px">
|
||||
<RoleList ref="roleList" />
|
||||
</a-col>
|
||||
<a-col flex="1" class="role-setting">
|
||||
<RoleSetting />
|
||||
</a-col>
|
||||
</a-row>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { computed, provide, ref } from 'vue';
|
||||
import RoleList from './components/role-list/index.vue';
|
||||
import RoleSetting from './components/role-setting/index.vue';
|
||||
defineProps({
|
||||
value: Object,
|
||||
});
|
||||
defineEmits(['update:value']);
|
||||
|
||||
let roleList = ref();
|
||||
const selectRoleId = computed(() => {
|
||||
if (!roleList.value) {
|
||||
return null;
|
||||
}
|
||||
return roleList.value.selectRoleId;
|
||||
});
|
||||
provide('selectRoleId', selectRoleId);
|
||||
</script>
|
||||
<style scoped lang="less">
|
||||
.height100 {
|
||||
height: 100%;
|
||||
}
|
||||
.role-setting {
|
||||
width: calc(100% - 250px);
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user