update: 角色管理over
This commit is contained in:
parent
a8af608299
commit
3b799e53d7
|
@ -91,6 +91,7 @@ const permission = reactive({
|
|||
},
|
||||
// 全选/取消全选
|
||||
selectAllOpions: (row: permissionType) => {
|
||||
row.indeterminate = false
|
||||
const newValue = props.value.filter(
|
||||
(item) => item.permission !== row.id,
|
||||
);
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<template>
|
||||
<div class="role-permiss-container">
|
||||
<a-card style="max-width: 60%">
|
||||
<a-card>
|
||||
<h5>基本信息</h5>
|
||||
<a-form ref="formRef" :model="form.data" layout="vertical">
|
||||
<a-form ref="formRef" class="basic-form" :model="form.data" layout="vertical">
|
||||
<a-form-item
|
||||
name="name"
|
||||
label="名称"
|
||||
|
@ -19,6 +19,7 @@
|
|||
v-model:value="form.data.description"
|
||||
placeholder="请输入说明"
|
||||
:maxlength="200"
|
||||
show-count
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
|
@ -32,6 +33,7 @@
|
|||
type="primary"
|
||||
:disabled="form.loading"
|
||||
@click="form.clickSave"
|
||||
style="margin-top: 24px;"
|
||||
>保存</a-button
|
||||
>
|
||||
</a-card>
|
||||
|
@ -70,7 +72,7 @@ const form = reactive({
|
|||
},
|
||||
clickSave: () => {
|
||||
const updateRole = updateRole_api(form.data);
|
||||
const updateTree = updatePrimissTree_api(roleId, { menu: form.menus });
|
||||
const updateTree = updatePrimissTree_api(roleId, { menus: form.menus });
|
||||
|
||||
Promise.all([updateRole, updateTree]).then((resp) => {
|
||||
message.success('操作成功');
|
||||
|
@ -82,4 +84,38 @@ const form = reactive({
|
|||
form.getForm();
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
<style lang="less" scoped>
|
||||
.role-permiss-container {
|
||||
.ant-card {
|
||||
margin-bottom: 24px;
|
||||
|
||||
h5 {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 20px;
|
||||
padding: 4px 0 4px 12px;
|
||||
font-weight: bold;
|
||||
font-size: 16px;
|
||||
|
||||
&::before {
|
||||
position: absolute;
|
||||
top: 5px px;
|
||||
left: 0;
|
||||
width: 4px;
|
||||
height: calc(100% - 10px);
|
||||
background-color: #1d39c4;
|
||||
border-radius: 2px;
|
||||
content: ' ';
|
||||
}
|
||||
}
|
||||
|
||||
.basic-form {
|
||||
.ant-form-item {
|
||||
display: block;
|
||||
width: 60%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -5,8 +5,9 @@
|
|||
:data-source="tableData"
|
||||
:pagination="false"
|
||||
:rowKey="'id'"
|
||||
:scroll="{ y: '500px' }"
|
||||
>
|
||||
<!-- 自定义表头 -->
|
||||
<!-- 表头 -->
|
||||
<template #headerCell="{ column }">
|
||||
<div v-if="column.key === 'menu'">
|
||||
<a-checkbox
|
||||
|
@ -18,9 +19,16 @@
|
|||
</div>
|
||||
<div v-else-if="column.key === 'data'">
|
||||
<span style="">数据权限</span>
|
||||
<a-tooltip>
|
||||
<template #title
|
||||
>勾选任意数据权限均能看到自己创建的数据权限</template
|
||||
>
|
||||
<question-circle-outlined />
|
||||
</a-tooltip>
|
||||
<a-checkbox
|
||||
v-model:checked="bulkShow"
|
||||
@change="bulkValue = ''"
|
||||
style="margin-left: 10px"
|
||||
>批量设置</a-checkbox
|
||||
>
|
||||
<a-select
|
||||
|
@ -30,19 +38,20 @@
|
|||
style="width: 200px"
|
||||
:options="bulkOptions"
|
||||
@change="bulkChange"
|
||||
placeholder="请选择"
|
||||
></a-select>
|
||||
</div>
|
||||
<div v-else>
|
||||
<span>{{ column.title }}</span>
|
||||
</div>
|
||||
</template>
|
||||
<!-- 自定义表格内容 -->
|
||||
<!-- 表格内容 -->
|
||||
<template #bodyCell="{ column, record }">
|
||||
<div v-if="column.key === 'menu'">
|
||||
<a-checkbox
|
||||
v-model:checked="record.granted"
|
||||
:indeterminate="record.indeterminate"
|
||||
@change="menuChange(record)"
|
||||
@change="menuChange(record, true)"
|
||||
>{{ record.name }}</a-checkbox
|
||||
>
|
||||
</div>
|
||||
|
@ -85,6 +94,7 @@
|
|||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { QuestionCircleOutlined } from '@ant-design/icons-vue';
|
||||
import { cloneDeep } from 'lodash-es';
|
||||
import { getPrimissTree_api } from '@/api/system/role';
|
||||
|
||||
|
@ -162,15 +172,28 @@ const flatTableData: tableItemType[] = []; // 表格数据的扁平化版本--
|
|||
|
||||
const init = () => {
|
||||
getAllPermiss();
|
||||
watch(tableData, () => {
|
||||
const selected = cloneDeep(flatTableData).filter((item) => (item.granted || item.indeterminate) && !item.parentId);
|
||||
// 监听权限的修改情况,产生修改后反馈给父组件
|
||||
watch(
|
||||
tableData,
|
||||
() => {
|
||||
// 深克隆表格数据的扁平版 因为会做一些改动 该改动只用于反馈给父组件,本组件无需变化
|
||||
const selected = cloneDeep(flatTableData).filter(
|
||||
(item) =>
|
||||
(item.granted && item.parentId) ||
|
||||
(item.indeterminate && item.buttons),
|
||||
);
|
||||
|
||||
selected.forEach((item) => {
|
||||
/**
|
||||
* 如果该项支持设置数据权限,则对其进行数据权限的映射,结束后删除用于映射的源属性,
|
||||
* 同时清除用于半全选状态的标记
|
||||
*/
|
||||
if (
|
||||
item.accessSupport &&
|
||||
item.accessSupport.value === 'support' &&
|
||||
item.selectAccesses
|
||||
) {
|
||||
item.selectAccesses = bulkValue.value;
|
||||
// item.selectAccesses = bulkValue.value;
|
||||
item.assetAccesses?.forEach((asset) => {
|
||||
if (asset.supportId === item.selectAccesses) {
|
||||
asset.granted = true;
|
||||
|
@ -180,13 +203,13 @@ const init = () => {
|
|||
});
|
||||
delete item.selectAccesses;
|
||||
}
|
||||
delete item.indeterminate
|
||||
delete item.indeterminate;
|
||||
item.granted = true;
|
||||
});
|
||||
emits(
|
||||
'update:selectItems',
|
||||
selected,
|
||||
emits('update:selectItems', selected);
|
||||
},
|
||||
{ deep: true },
|
||||
);
|
||||
});
|
||||
};
|
||||
init();
|
||||
|
||||
|
@ -218,6 +241,7 @@ function menuChange(
|
|||
row: tableItemType,
|
||||
setButtonBool: boolean = true,
|
||||
): undefined {
|
||||
// 判断是否需要对子菜单及操作权限进行选择
|
||||
if (setButtonBool) {
|
||||
if (row.buttons && row.buttons.length > 0)
|
||||
row.buttons.forEach((button) => {
|
||||
|
@ -225,34 +249,32 @@ function menuChange(
|
|||
});
|
||||
row.children && setChildrenChecked(row.children, row.granted);
|
||||
}
|
||||
|
||||
// 改变上层节点的状态
|
||||
const selectList = flatTableData.filter((item) => item.granted); // 第一列选中的项
|
||||
// 更新选中状态
|
||||
if (row.buttons && row.buttons.length > 0) setStatus(row, 'buttons');
|
||||
else setStatus(row, 'children');
|
||||
// 更新数据权限
|
||||
if (row.selectAccesses !== undefined) {
|
||||
if (!row.granted) {
|
||||
row.selectAccesses = '';
|
||||
} else if (row.selectAccesses === '') {
|
||||
row.selectAccesses = 'creator';
|
||||
}
|
||||
}
|
||||
// 更新上层节点的状态
|
||||
if (row.parentId) {
|
||||
// 找到对应的父节点 判断该父节点的选中状态为 全选中/部分选中/未选中
|
||||
const parent = flatTableData.find(
|
||||
(item) => item.id === row.parentId,
|
||||
) as tableItemType;
|
||||
const selectLen = parent.children?.filter((item) => item.granted)
|
||||
.length as number; // 父节点的已选中子节点的数量
|
||||
|
||||
if (selectLen === parent.children?.length) {
|
||||
parent.granted = true;
|
||||
parent.indeterminate = false;
|
||||
} else if (selectLen > 0) {
|
||||
parent.granted = false;
|
||||
parent.indeterminate = true;
|
||||
} else {
|
||||
parent.granted = false;
|
||||
parent.indeterminate = false;
|
||||
}
|
||||
|
||||
setStatus(parent, 'children');
|
||||
// 若该父节点不是根节点 重复此操作以此来确定该父节点的父节点状态
|
||||
if (parent.parentId) {
|
||||
return menuChange(parent, false);
|
||||
}
|
||||
}
|
||||
|
||||
// 改变头部节点状态
|
||||
const selectList = flatTableData.filter((item) => item.granted); // 第一列选中的项
|
||||
if (selectList.length === flatTableData.length) {
|
||||
selectedAll.value = true;
|
||||
indeterminate.value = false;
|
||||
|
@ -270,20 +292,7 @@ function menuChange(
|
|||
* @param row 触发的项
|
||||
*/
|
||||
function actionChange(row: tableItemType) {
|
||||
const selectLen = row.buttons?.filter((item) => item.granted)
|
||||
.length as number;
|
||||
|
||||
if (selectLen === row.buttons?.length) {
|
||||
row.granted = true;
|
||||
row.indeterminate = false;
|
||||
} else if (selectLen > 0) {
|
||||
row.granted = false;
|
||||
row.indeterminate = true;
|
||||
} else {
|
||||
row.granted = false;
|
||||
row.indeterminate = false;
|
||||
}
|
||||
|
||||
setStatus(row, 'buttons');
|
||||
menuChange(row, false);
|
||||
}
|
||||
|
||||
|
@ -293,12 +302,15 @@ function actionChange(row: tableItemType) {
|
|||
*/
|
||||
function treeToSimple(treeData: tableItemType[]) {
|
||||
treeData.forEach((item) => {
|
||||
// 数据权限回填
|
||||
if (item.accessSupport && item.accessSupport.value === 'support') {
|
||||
const select =
|
||||
item.assetAccesses?.find((assetItem) => assetItem.granted) ||
|
||||
{};
|
||||
item.selectAccesses = select.supportId || '';
|
||||
}
|
||||
if (item.buttons && item.buttons.length > 0) setStatus(item, 'buttons');
|
||||
else setStatus(item, 'children');
|
||||
flatTableData.push(item);
|
||||
item.children && treeToSimple(item.children);
|
||||
});
|
||||
|
@ -312,6 +324,7 @@ function setChildrenChecked(childrens: tableItemType[], value: boolean) {
|
|||
if (childrens.length < 1) return;
|
||||
childrens.forEach((item) => {
|
||||
item.granted = value;
|
||||
item.indeterminate = false;
|
||||
if (item.buttons && item.buttons.length > 0)
|
||||
item.buttons.forEach((button) => {
|
||||
button.granted = value;
|
||||
|
@ -319,11 +332,49 @@ function setChildrenChecked(childrens: tableItemType[], value: boolean) {
|
|||
item.children && setChildrenChecked(item.children, value);
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 根据taget的prop属性,判断对应的全选状态,头部全选不适用
|
||||
* @param target 目标对象
|
||||
* @param prop 目标属性
|
||||
*/
|
||||
function setStatus(
|
||||
target: tableItemType,
|
||||
prop: 'children' | 'buttons' = 'children',
|
||||
) {
|
||||
const childrens = target[prop] as any[];
|
||||
|
||||
if (childrens && childrens instanceof Array) {
|
||||
// 如果子选项有半全选,则当前节点直接为半全选
|
||||
const indeterminateLen = childrens.filter(
|
||||
(childrens: buttonItemType | tableItemType) =>
|
||||
childrens?.indeterminate,
|
||||
).length;
|
||||
if (indeterminateLen > 0) {
|
||||
target.granted = false;
|
||||
target.indeterminate = true;
|
||||
return;
|
||||
}
|
||||
|
||||
const selectLen = childrens.filter(
|
||||
(children: buttonItemType | tableItemType) => children.granted,
|
||||
).length;
|
||||
if (selectLen === childrens.length) {
|
||||
target.granted = true;
|
||||
target.indeterminate = false;
|
||||
} else if (selectLen > 0) {
|
||||
target.granted = false;
|
||||
target.indeterminate = true;
|
||||
} else {
|
||||
target.granted = false;
|
||||
target.indeterminate = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
type buttonItemType = {
|
||||
supportId: string;
|
||||
name: string;
|
||||
granted: boolean;
|
||||
indeterminate?: boolean;
|
||||
};
|
||||
type tableItemType = {
|
||||
id: string;
|
||||
|
|
|
@ -25,7 +25,7 @@ const activeKey = ref('1');
|
|||
padding: 24px 0 0 24px;
|
||||
}
|
||||
|
||||
.role-permiss-container {
|
||||
:deep(.ant-tabs-content-holder) {
|
||||
padding: 24px;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,6 +61,8 @@ import { getRoleList_api, delRole_api } from '@/api/system/role';
|
|||
import { message } from 'ant-design-vue';
|
||||
const addDialogRef = ref(); // 新增弹窗实例
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
|
||||
// 筛选
|
||||
const query = reactive({
|
||||
columns: [
|
||||
|
@ -122,7 +124,7 @@ const table = reactive({
|
|||
],
|
||||
tableData: [],
|
||||
clickAdd: () => {
|
||||
addDialogRef.value.openDialog(true, {})
|
||||
addDialogRef.value.openDialog(true, {});
|
||||
},
|
||||
clickDel: (row: any) => {
|
||||
delRole_api(row.id).then((resp: any) => {
|
||||
|
@ -136,7 +138,9 @@ const table = reactive({
|
|||
router.push(`/system/Role/detail/${row.id}`);
|
||||
},
|
||||
});
|
||||
|
||||
nextTick(() => {
|
||||
route.query.save && table.clickAdd();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
|
|
29
yarn.lock
29
yarn.lock
|
@ -1611,9 +1611,9 @@ combined-stream@^1.0.8:
|
|||
dependencies:
|
||||
delayed-stream "~1.0.0"
|
||||
|
||||
commander@^2.19.0, commander@^2.20.0:
|
||||
commander@^2.19.0, commander@^2.20.0, commander@^2.20.3:
|
||||
version "2.20.3"
|
||||
resolved "https://registry.npmmirror.com/commander/-/commander-2.20.3.tgz"
|
||||
resolved "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
|
||||
integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
|
||||
|
||||
commander@^8.3.0:
|
||||
|
@ -1832,6 +1832,11 @@ css-what@^6.0.1:
|
|||
resolved "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz"
|
||||
integrity sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==
|
||||
|
||||
cssfilter@0.0.10:
|
||||
version "0.0.10"
|
||||
resolved "https://registry.npmjs.org/cssfilter/-/cssfilter-0.0.10.tgz#c6d2672632a2e5c83e013e6864a42ce8defd20ae"
|
||||
integrity sha512-FAaLDaplstoRsDR8XGYH51znUN0UY7nMc6Z9/fvE8EXGwvJE9hu7W2vHwx1+bd6gCYnln9nLbzxFTrcO9YQDZw==
|
||||
|
||||
csstype@^2.6.8:
|
||||
version "2.6.21"
|
||||
resolved "https://registry.npmjs.org/csstype/-/csstype-2.6.21.tgz"
|
||||
|
@ -1988,6 +1993,11 @@ dotenv@^5.0.1:
|
|||
resolved "https://registry.npmmirror.com/dotenv/-/dotenv-5.0.1.tgz"
|
||||
integrity sha512-4As8uPrjfwb7VXC+WnLCbXK7y+Ueb2B3zgNCePYfhxS1PYeaO1YTeplffTEcbfLhvFNGLAz90VvJs9yomG7bow==
|
||||
|
||||
driver.js@^0.9.8:
|
||||
version "0.9.8"
|
||||
resolved "https://registry.npmjs.org/driver.js/-/driver.js-0.9.8.tgz#4b327f4537b1c9b9fb19419de86174be821ae32a"
|
||||
integrity sha512-bczjyKdX6XmFyCDkwtRmlaORDwfBk1xXmRO0CAe5VwNQTM98aWaG2LAIiIdTe53iV/B7W5lXlIy2xYtf0JRb7Q==
|
||||
|
||||
duplexer3@^0.1.4:
|
||||
version "0.1.5"
|
||||
resolved "https://registry.npmmirror.com/duplexer3/-/duplexer3-0.1.5.tgz"
|
||||
|
@ -3366,6 +3376,13 @@ markdown-it@^12.3.2:
|
|||
mdurl "^1.0.1"
|
||||
uc.micro "^1.0.5"
|
||||
|
||||
mavon-editor@^2.10.4:
|
||||
version "2.10.4"
|
||||
resolved "https://registry.npmjs.org/mavon-editor/-/mavon-editor-2.10.4.tgz#58d6c4dc208933f0ac4595c10c60655899ba8ba8"
|
||||
integrity sha512-CFsBLkgt/KZBDg+SJYe2fyYv4zClY149PiwpH0rDAiiP4ae1XNs0GC8nBsoTeipsHcebDLN1QMkt3bUsnMDjQw==
|
||||
dependencies:
|
||||
xss "^1.0.6"
|
||||
|
||||
mdurl@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.npmmirror.com/mdurl/-/mdurl-1.0.1.tgz"
|
||||
|
@ -5255,6 +5272,14 @@ xdg-basedir@^4.0.0:
|
|||
resolved "https://registry.npmmirror.com/xdg-basedir/-/xdg-basedir-4.0.0.tgz"
|
||||
integrity sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==
|
||||
|
||||
xss@^1.0.6:
|
||||
version "1.0.14"
|
||||
resolved "https://registry.npmjs.org/xss/-/xss-1.0.14.tgz#4f3efbde75ad0d82e9921cc3c95e6590dd336694"
|
||||
integrity sha512-og7TEJhXvn1a7kzZGQ7ETjdQVS2UfZyTlsEdDOqvQF7GoxNfY+0YLCzBy1kPdsDDx4QuNAonQPddpsn6Xl/7sw==
|
||||
dependencies:
|
||||
commander "^2.20.3"
|
||||
cssfilter "0.0.10"
|
||||
|
||||
y18n@^4.0.0:
|
||||
version "4.0.3"
|
||||
resolved "https://registry.npmmirror.com/y18n/-/y18n-4.0.3.tgz"
|
||||
|
|
Loading…
Reference in New Issue