commit
607eefd5f7
|
@ -1,388 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="setting-container">
|
|
||||||
<h5 class="top">
|
|
||||||
<AIcon type="ExclamationCircleOutlined" />
|
|
||||||
<span style="padding-left: 12px"
|
|
||||||
>基于系统源代码中的菜单数据,配置系统菜单。</span
|
|
||||||
>
|
|
||||||
</h5>
|
|
||||||
|
|
||||||
<div class="transfer">
|
|
||||||
<!-- 左侧树 -->
|
|
||||||
<div class="basic-tree left">
|
|
||||||
<div class="title">
|
|
||||||
<div class="title-label">
|
|
||||||
<span>源菜单</span>
|
|
||||||
<j-tooltip>
|
|
||||||
<template #title
|
|
||||||
>根据系统代码自动读取的菜单数据</template
|
|
||||||
>
|
|
||||||
<AIcon type="QuestionCircleOutlined" />
|
|
||||||
</j-tooltip>
|
|
||||||
</div>
|
|
||||||
<div class="title-func">
|
|
||||||
<j-button
|
|
||||||
type="primary"
|
|
||||||
@click="dialogShow = true"
|
|
||||||
ghost
|
|
||||||
>一键拷贝</j-button
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="content">
|
|
||||||
<j-input
|
|
||||||
v-model:value="transfer.data.leftSearchValue"
|
|
||||||
style="margin-bottom: 8px"
|
|
||||||
placeholder="请输入菜单名称"
|
|
||||||
@change="transfer.changeTreeLeft"
|
|
||||||
>
|
|
||||||
<template #prefix>
|
|
||||||
<AIcon
|
|
||||||
type="SearchOutlined"
|
|
||||||
style="color: #b3b3b3"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
</j-input>
|
|
||||||
<j-tree
|
|
||||||
v-if="transfer.data.leftTreeData.length !== 0"
|
|
||||||
:tree-data="transfer.data.leftTreeData"
|
|
||||||
draggable
|
|
||||||
defaultExpandAll
|
|
||||||
:height="550"
|
|
||||||
>
|
|
||||||
<template #title="row">
|
|
||||||
<div>{{ row.name }}</div>
|
|
||||||
</template>
|
|
||||||
</j-tree>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="center">
|
|
||||||
<j-button>请拖动至右侧</j-button>
|
|
||||||
</div>
|
|
||||||
<!-- 右侧树 -->
|
|
||||||
<div class="basic-tree right">
|
|
||||||
<div class="title">
|
|
||||||
<div class="title-label">
|
|
||||||
<span>系统菜单</span>
|
|
||||||
<j-tooltip>
|
|
||||||
<template #title
|
|
||||||
>菜单管理页面配置的菜单数据</template
|
|
||||||
>
|
|
||||||
<AIcon type="QuestionCircleOutlined" />
|
|
||||||
</j-tooltip>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="content">
|
|
||||||
<j-input
|
|
||||||
v-model:value="transfer.data.rightSearchValue"
|
|
||||||
style="margin-bottom: 8px"
|
|
||||||
placeholder="请输入菜单名称"
|
|
||||||
@change="transfer.changeTreeRight"
|
|
||||||
>
|
|
||||||
<template #prefix>
|
|
||||||
<AIcon
|
|
||||||
type="SearchOutlined"
|
|
||||||
style="color: #b3b3b3"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
</j-input>
|
|
||||||
|
|
||||||
<j-tree
|
|
||||||
v-if="transfer.data.rightTreeData.length !== 0"
|
|
||||||
draggable
|
|
||||||
defaultExpandAll
|
|
||||||
:tree-data="transfer.data.rightTreeData"
|
|
||||||
@drop="transfer.onRightDrop"
|
|
||||||
:height="550"
|
|
||||||
>
|
|
||||||
<template #title="row">
|
|
||||||
<div
|
|
||||||
style="
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<span>{{ row.name }}</span>
|
|
||||||
<j-popconfirm
|
|
||||||
title="确认删除?"
|
|
||||||
ok-text="确定"
|
|
||||||
cancel-text="取消"
|
|
||||||
@confirm="transfer.removeItem(row)"
|
|
||||||
placement="topRight"
|
|
||||||
>
|
|
||||||
<j-tooltip>
|
|
||||||
<template #title>删除</template>
|
|
||||||
<j-button
|
|
||||||
style="
|
|
||||||
padding: 0;
|
|
||||||
margin-right: 12px;
|
|
||||||
"
|
|
||||||
type="link"
|
|
||||||
>
|
|
||||||
<AIcon type="CloseOutlined" />
|
|
||||||
</j-button>
|
|
||||||
</j-tooltip>
|
|
||||||
</j-popconfirm>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</j-tree>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<j-button type="primary" style="margin-top: 24px">保存</j-button>
|
|
||||||
|
|
||||||
<div class="dialogs">
|
|
||||||
<j-modal
|
|
||||||
v-model:visible="dialogShow"
|
|
||||||
title="一键拷贝"
|
|
||||||
@ok="transfer.copy"
|
|
||||||
cancelText="取消"
|
|
||||||
okText="确认"
|
|
||||||
>
|
|
||||||
<p>源数据将会覆盖当前的系统菜单数据,确定要一键拷贝吗?</p>
|
|
||||||
</j-modal>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts" name="MenuSetting">
|
|
||||||
import { getMenuTree_api } from '@/api/system/menu';
|
|
||||||
import { getSystemPermission as getSystemPermission_api } from '@/api/initHome';
|
|
||||||
import { filterMenu, getKeys, loop } from './utils';
|
|
||||||
import BaseTreeData from './baseMenu';
|
|
||||||
import type {
|
|
||||||
AntTreeNodeDropEvent,
|
|
||||||
TreeDataItem,
|
|
||||||
TreeProps,
|
|
||||||
} from 'ant-design-vue/es/tree';
|
|
||||||
import { treeFilter } from '@/utils/tree';
|
|
||||||
import { cloneDeep } from 'lodash';
|
|
||||||
|
|
||||||
const transfer = {
|
|
||||||
data: reactive({
|
|
||||||
// 左侧树
|
|
||||||
leftSearchValue: '',
|
|
||||||
leftTreeData: [] as any[],
|
|
||||||
|
|
||||||
// 右侧树
|
|
||||||
rightSearchValue: '',
|
|
||||||
rightTreeData: [] as any[],
|
|
||||||
}),
|
|
||||||
leftSourceData: [] as any[],
|
|
||||||
rightSourceData: [] as any[],
|
|
||||||
|
|
||||||
init: () => {
|
|
||||||
// 源菜单
|
|
||||||
const sourceMenu = getSystemPermission_api().then((resp: any) => {
|
|
||||||
const newTree = filterMenu(
|
|
||||||
resp.result.map((item: any) => JSON.parse(item).id),
|
|
||||||
BaseTreeData,
|
|
||||||
);
|
|
||||||
transfer.leftSourceData = [...newTree];
|
|
||||||
transfer.data.leftTreeData = newTree;
|
|
||||||
});
|
|
||||||
const params = {
|
|
||||||
paging: false,
|
|
||||||
terms: [
|
|
||||||
{
|
|
||||||
terms: [
|
|
||||||
{
|
|
||||||
column: 'owner',
|
|
||||||
termType: 'eq',
|
|
||||||
value: 'iot',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
column: 'owner',
|
|
||||||
termType: 'isnull',
|
|
||||||
value: '1',
|
|
||||||
type: 'or',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
// 系统菜单
|
|
||||||
const systemMenu = getMenuTree_api(params).then((resp: any) => {
|
|
||||||
transfer.data.rightTreeData = resp.result;
|
|
||||||
transfer.rightSourceData = [...resp.result];
|
|
||||||
});
|
|
||||||
// 当两个菜单的源数据都获取到之后,对左侧菜单进行更新,更新每项是否需要禁用
|
|
||||||
Promise.all([sourceMenu, systemMenu]).then(() => transfer.updateTree());
|
|
||||||
},
|
|
||||||
copy: () => {
|
|
||||||
transfer.data.rightTreeData = [...toRaw(transfer.data.leftTreeData)];
|
|
||||||
dialogShow.value = false;
|
|
||||||
},
|
|
||||||
removeItem: (row: any) => {
|
|
||||||
loop(
|
|
||||||
transfer.data.rightTreeData,
|
|
||||||
row.id,
|
|
||||||
(item: TreeDataItem, index: number, arr: TreeProps['treeData']) => {
|
|
||||||
arr?.splice(index, 1);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
transfer.updateTree();
|
|
||||||
},
|
|
||||||
onRightDrop: (info: AntTreeNodeDropEvent) => {
|
|
||||||
const dropKey = info.node.id;
|
|
||||||
const dragKey = info.dragNode.id;
|
|
||||||
const dropPos = (info.node.pos && info.node.pos.split('-')) || [];
|
|
||||||
const dropPosition =
|
|
||||||
info.dropPosition - Number(dropPos[dropPos.length - 1]);
|
|
||||||
const data = [...transfer.data.rightTreeData];
|
|
||||||
let dragObj: TreeDataItem = { key: '' };
|
|
||||||
loop(
|
|
||||||
data,
|
|
||||||
dragKey,
|
|
||||||
(item: TreeDataItem, index: number, arr: TreeProps['treeData']) => {
|
|
||||||
arr?.splice(index, 1);
|
|
||||||
dragObj = item;
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!info.dropToGap) {
|
|
||||||
// Drop on the content
|
|
||||||
loop(data, dropKey, (item: TreeDataItem) => {
|
|
||||||
item.children = item.children || [];
|
|
||||||
/// where to insert 示例添加到头部,可以是随意位置
|
|
||||||
item.children.unshift(dragObj);
|
|
||||||
});
|
|
||||||
} else if (
|
|
||||||
(info.node.children || []).length > 0 && // Has children
|
|
||||||
info.node.expanded && // Is expanded
|
|
||||||
dropPosition === 1 // On the bottom gap
|
|
||||||
) {
|
|
||||||
loop(data, dropKey, (item: TreeDataItem) => {
|
|
||||||
item.children = item.children || [];
|
|
||||||
// where to insert 示例添加到头部,可以是随意位置
|
|
||||||
item.children.unshift(dragObj);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
let ar: TreeProps['treeData'] = [];
|
|
||||||
let i = 0;
|
|
||||||
loop(
|
|
||||||
data,
|
|
||||||
dropKey,
|
|
||||||
(
|
|
||||||
_item: TreeDataItem,
|
|
||||||
index: number,
|
|
||||||
arr: TreeProps['treeData'],
|
|
||||||
) => {
|
|
||||||
ar = arr;
|
|
||||||
i = index;
|
|
||||||
},
|
|
||||||
);
|
|
||||||
if (dropPosition === -1) {
|
|
||||||
ar.splice(i, 0, dragObj);
|
|
||||||
} else {
|
|
||||||
ar.splice(i + 1, 0, dragObj);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
transfer.data.rightTreeData = data;
|
|
||||||
},
|
|
||||||
updateTree: () => {
|
|
||||||
console.log(getKeys(transfer.data.rightTreeData));
|
|
||||||
},
|
|
||||||
changeTreeLeft: (val: any) => {
|
|
||||||
const value = val.target.value;
|
|
||||||
if (value) {
|
|
||||||
transfer.data.leftTreeData = treeFilter(
|
|
||||||
transfer.leftSourceData,
|
|
||||||
value,
|
|
||||||
'name',
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
transfer.data.leftTreeData = cloneDeep(transfer.rightSourceData);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
changeTreeRight: (val: any) => {
|
|
||||||
const value = val.target.value;
|
|
||||||
if (value) {
|
|
||||||
transfer.data.rightTreeData = treeFilter(
|
|
||||||
transfer.rightSourceData,
|
|
||||||
value,
|
|
||||||
'name',
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
transfer.data.rightTreeData = cloneDeep(transfer.rightSourceData);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
transfer.init();
|
|
||||||
|
|
||||||
const dialogShow = ref<boolean>(false);
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="less" scoped>
|
|
||||||
.setting-container {
|
|
||||||
padding: 24px;
|
|
||||||
margin: 24px;
|
|
||||||
background-color: #fff;
|
|
||||||
|
|
||||||
.top {
|
|
||||||
font-size: inherit;
|
|
||||||
margin-bottom: 24px;
|
|
||||||
padding: 10px 24px;
|
|
||||||
color: rgba(0, 0, 0, 0.55);
|
|
||||||
background-color: #f6f6f6;
|
|
||||||
}
|
|
||||||
|
|
||||||
.transfer {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
|
|
||||||
.basic-tree {
|
|
||||||
flex: 1;
|
|
||||||
|
|
||||||
.title {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
margin-bottom: 16px;
|
|
||||||
padding: 14px 16px;
|
|
||||||
font-weight: 400;
|
|
||||||
font-size: 16px;
|
|
||||||
background-color: #f3f4f4;
|
|
||||||
|
|
||||||
.title-label {
|
|
||||||
span {
|
|
||||||
padding-right: 12px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.content {
|
|
||||||
padding: 12px;
|
|
||||||
border: 1px solid #e0e0e0;
|
|
||||||
border-radius: 4px;
|
|
||||||
|
|
||||||
.ant-input-affix-wrapper {
|
|
||||||
width: 75%;
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(.ant-tree) {
|
|
||||||
height: 550px;
|
|
||||||
overflow: auto;
|
|
||||||
.ant-tree-list-holder-inner {
|
|
||||||
> .ant-tree-treenode {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
.ant-tree-node-content-wrapper {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.center {
|
|
||||||
flex-basis: 120px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
margin: 0 24px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -3,84 +3,84 @@
|
||||||
<j-card>
|
<j-card>
|
||||||
<div class="top">
|
<div class="top">
|
||||||
<AIcon style="padding: 12px" type="ExclamationCircleOutlined" />
|
<AIcon style="padding: 12px" type="ExclamationCircleOutlined" />
|
||||||
<span>基于系统源代码中的菜单数据,配置系统菜单。</span>
|
<span
|
||||||
|
>单击可切换菜单未选中/选中状态;操作父级菜单时,对应子菜单状态将默认与其同步,可以单独操作调整;支持拖拽菜单调整展示顺序。
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<div class="title">
|
<j-card title="菜单配置" style="width: 80%">
|
||||||
系统菜单
|
<div class="tree">
|
||||||
<j-tooltip>
|
<j-tree
|
||||||
<template #title
|
v-if="treeData.length !== 0"
|
||||||
>根据系统代码自动读取的菜单数据</template
|
show-line
|
||||||
|
defaultExpandAll
|
||||||
|
multiple
|
||||||
|
draggable
|
||||||
|
:tree-data="treeData"
|
||||||
|
:height="520"
|
||||||
|
@select="onSelect"
|
||||||
|
:selectedKeys="selectedKeys"
|
||||||
|
@drop="onDrop"
|
||||||
>
|
>
|
||||||
<AIcon type="QuestionCircleOutlined" />
|
<template #title="row">
|
||||||
</j-tooltip>
|
<div class="tree-content">
|
||||||
</div>
|
<div class="tree-content-title">
|
||||||
<div class="tree">
|
<AIcon type="HolderOutlined" />
|
||||||
<j-input
|
<div style="margin-left: 8px">
|
||||||
v-model="filterText"
|
{{ row.name }}
|
||||||
placeholder="请输入"
|
</div>
|
||||||
@change="change"
|
|
||||||
style="margin-bottom: 12px"
|
|
||||||
/>
|
|
||||||
<j-tree
|
|
||||||
v-if="treeData.length !== 0"
|
|
||||||
show-line
|
|
||||||
defaultExpandAll
|
|
||||||
multiple
|
|
||||||
draggable
|
|
||||||
:tree-data="treeData"
|
|
||||||
:height="500"
|
|
||||||
@select="onSelect"
|
|
||||||
:selectedKeys="selectedKeys"
|
|
||||||
@drop="onDrop"
|
|
||||||
>
|
|
||||||
<template #title="row">
|
|
||||||
<div class="tree-content">
|
|
||||||
<div class="tree-content-title">
|
|
||||||
<AIcon type="HolderOutlined" />
|
|
||||||
<div style="margin-left: 8px">
|
|
||||||
{{ row.name }}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</template>
|
||||||
</template>
|
</j-tree>
|
||||||
</j-tree>
|
</div>
|
||||||
</div>
|
</j-card>
|
||||||
<j-button type="primary">保存</j-button>
|
|
||||||
</div>
|
</div>
|
||||||
|
<j-button
|
||||||
|
type="primary"
|
||||||
|
@click="() => (visible = true)"
|
||||||
|
style="margin-left: 10%"
|
||||||
|
>保存</j-button
|
||||||
|
>
|
||||||
</j-card>
|
</j-card>
|
||||||
|
<j-modal
|
||||||
|
:visible="visible"
|
||||||
|
@ok="handleOk"
|
||||||
|
@cancel="handleCancel"
|
||||||
|
modalType="message"
|
||||||
|
:confirmLoading="loading"
|
||||||
|
>
|
||||||
|
保存后当前系统菜单数据将被覆盖,确认操作?
|
||||||
|
</j-modal>
|
||||||
</page-container>
|
</page-container>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts" name="MenuSetting">
|
<script setup lang="ts" name="MenuSetting">
|
||||||
import { getMenuTree_api } from '@/api/system/menu';
|
import { getMenuTree_api } from '@/api/system/menu';
|
||||||
import { getSystemPermission as getSystemPermission_api } from '@/api/initHome';
|
import {
|
||||||
|
getSystemPermission as getSystemPermission_api,
|
||||||
|
updateMenus,
|
||||||
|
} from '@/api/initHome';
|
||||||
import {
|
import {
|
||||||
filterMenu,
|
filterMenu,
|
||||||
mergeMapToArr,
|
mergeMapToArr,
|
||||||
developArrToMap,
|
developArrToMap,
|
||||||
drop,
|
drop,
|
||||||
select,
|
select,
|
||||||
|
getMaxDepth,
|
||||||
} from './utils';
|
} from './utils';
|
||||||
import BaseMenu from './baseMenu';
|
import BaseMenu from './baseMenu';
|
||||||
import type { AntTreeNodeDropEvent } from 'ant-design-vue/es/tree';
|
import type { AntTreeNodeDropEvent } from 'ant-design-vue/es/tree';
|
||||||
import { treeFilter } from '@/utils/tree';
|
|
||||||
import { cloneDeep } from 'lodash';
|
import { cloneDeep } from 'lodash';
|
||||||
|
import { onlyMessage } from '@/utils/comm';
|
||||||
|
|
||||||
const selectedKeys: any = ref([]);
|
const selectedKeys: any = ref([]);
|
||||||
const treeData = ref<any>([]);
|
const treeData = ref<any>([]);
|
||||||
const filterText = ref('');
|
|
||||||
const systemMenu: any = ref([]);
|
const systemMenu: any = ref([]);
|
||||||
const baseMenu: any = ref([]);
|
const baseMenu: any = ref([]);
|
||||||
const AllMenu = ref([]);
|
const AllMenu = ref([]);
|
||||||
|
const visible = ref(false);
|
||||||
const onSelect = (selecteds: Array<string>, e: any) => {
|
const loading = ref(false);
|
||||||
selectedKeys.value = select(selecteds, e);
|
|
||||||
};
|
|
||||||
|
|
||||||
const onDrop = (info: AntTreeNodeDropEvent) => {
|
|
||||||
treeData.value = drop(info, treeData.value);
|
|
||||||
};
|
|
||||||
|
|
||||||
const params = {
|
const params = {
|
||||||
paging: false,
|
paging: false,
|
||||||
|
@ -103,8 +103,33 @@ const params = {
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
const change = (val: any) => {
|
const handleOk = async () => {
|
||||||
treeData.value = treeFilter(AllMenu.value, val.target.value, 'name');
|
loading.value = true;
|
||||||
|
const res = await updateMenus(treeData.value);
|
||||||
|
if (res.status === 200) {
|
||||||
|
onlyMessage('操作成功', 'success');
|
||||||
|
}
|
||||||
|
loading.value = false;
|
||||||
|
visible.value = false;
|
||||||
|
};
|
||||||
|
const handleCancel = () => {
|
||||||
|
visible.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const onSelect = (selecteds: Array<string>, e: any) => {
|
||||||
|
selectedKeys.value = select(selecteds, e);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onDrop = (info: AntTreeNodeDropEvent) => {
|
||||||
|
const TreeData = cloneDeep(treeData.value);
|
||||||
|
const newTreeData = drop(info, treeData.value);
|
||||||
|
const maxDepth = getMaxDepth(newTreeData);
|
||||||
|
if (maxDepth > 3) {
|
||||||
|
onlyMessage('仅支持3级菜单', 'error');
|
||||||
|
treeData.value = TreeData;
|
||||||
|
} else {
|
||||||
|
treeData.value = newTreeData;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
@ -116,6 +141,7 @@ onMounted(() => {
|
||||||
getMenuTree_api(params).then((resp: any) => {
|
getMenuTree_api(params).then((resp: any) => {
|
||||||
if (resp.status == 200) {
|
if (resp.status == 200) {
|
||||||
systemMenu.value = resp.result;
|
systemMenu.value = resp.result;
|
||||||
|
//初始化菜单
|
||||||
const baseMenuData = developArrToMap(baseMenu.value);
|
const baseMenuData = developArrToMap(baseMenu.value);
|
||||||
const systemMenuData = developArrToMap(systemMenu.value, true);
|
const systemMenuData = developArrToMap(systemMenu.value, true);
|
||||||
selectedKeys.value = systemMenuData.checkedKeys;
|
selectedKeys.value = systemMenuData.checkedKeys;
|
||||||
|
@ -136,19 +162,14 @@ onMounted(() => {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
line-height: 20px;
|
line-height: 20px;
|
||||||
color: rgba(0, 0, 0, 0.55);
|
color: rgba(0, 0, 0, 0.55);
|
||||||
|
margin-bottom: 12px;
|
||||||
}
|
}
|
||||||
.content {
|
.content {
|
||||||
width: 50%;
|
width: 100%;
|
||||||
margin-top: 24px;
|
margin: 12px 0;
|
||||||
.title {
|
display: flex;
|
||||||
font-style: normal;
|
justify-content: center;
|
||||||
font-weight: 800;
|
// flex-direction: row;
|
||||||
font-size: 16px;
|
|
||||||
height: 48px;
|
|
||||||
padding: 12px;
|
|
||||||
background: #f3f4f4;
|
|
||||||
color: rgba(0, 0, 0, 0.8);
|
|
||||||
}
|
|
||||||
:deep(.ant-tree) {
|
:deep(.ant-tree) {
|
||||||
.ant-tree-switcher {
|
.ant-tree-switcher {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -165,12 +186,16 @@ onMounted(() => {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
:deep(.ant-card-body) {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.tree {
|
.tree {
|
||||||
height: 580px;
|
// flex: 1;
|
||||||
|
height: 540px;
|
||||||
margin: 16px 0;
|
margin: 16px 0;
|
||||||
padding: 12px;
|
padding: 12px;
|
||||||
background: #ffffff;
|
background: #ffffff;
|
||||||
border: 1px solid #e0e0e0;
|
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -178,6 +203,8 @@ onMounted(() => {
|
||||||
&-content {
|
&-content {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
margin: 5px 0;
|
||||||
|
|
||||||
&-title {
|
&-title {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
|
|
|
@ -61,20 +61,20 @@ export const developArrToMap = (Menu: any, checked = false) => {
|
||||||
const rootSet = new Set();
|
const rootSet = new Set();
|
||||||
const arrMap = new Map();
|
const arrMap = new Map();
|
||||||
const checkedKeys: any = [];
|
const checkedKeys: any = [];
|
||||||
const getMap = (arr: any, parentCode = 'root', preKey = '0') => {
|
const getMap = (arr: any, parentCode = 'root') => {
|
||||||
arr.forEach((item: any, index: number) => {
|
arr.forEach((item: any) => {
|
||||||
const key = preKey + `-${index}`; //初始化key
|
|
||||||
item.title = item.code;
|
item.title = item.code;
|
||||||
item.key = key;
|
item.key = item.code;
|
||||||
if (checked) {
|
if (checked || item?.checked) {
|
||||||
checkedKeys.push(key);
|
item.checked = item?.checked || checked;
|
||||||
|
checkedKeys.push(item.code);
|
||||||
}
|
}
|
||||||
arrMap.set(item.code, item);
|
arrMap.set(item.code, item);
|
||||||
if (parentCode === 'root') {
|
if (parentCode === 'root') {
|
||||||
rootSet.add(item.code); //处理根菜单
|
rootSet.add(item.code); //处理根菜单
|
||||||
}
|
}
|
||||||
if (item?.children) {
|
if (item?.children) {
|
||||||
getMap(item?.children, item.code, key);
|
getMap(item?.children, item.code);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -91,17 +91,16 @@ export const developArrToMap = (Menu: any, checked = false) => {
|
||||||
export const select = (selecteds: Array<string>, e: any) => {
|
export const select = (selecteds: Array<string>, e: any) => {
|
||||||
const { node } = e;
|
const { node } = e;
|
||||||
const childKeys: Array<string> = [];
|
const childKeys: Array<string> = [];
|
||||||
const getChildKeys = (data: any, preKey = '0') => {
|
const getChildKeys = (data: any) => {
|
||||||
data.forEach((item: any, index: number) => {
|
data.forEach((item: any) => {
|
||||||
const checkedKey = preKey + `-${index}`;
|
childKeys.push(item.code);
|
||||||
childKeys.push(checkedKey);
|
|
||||||
if (item?.children) {
|
if (item?.children) {
|
||||||
getChildKeys(item?.children, checkedKey);
|
getChildKeys(item?.children);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
if (node?.children) {
|
if (node?.children) {
|
||||||
getChildKeys(node.children, node.key);
|
getChildKeys(node.children);
|
||||||
}
|
}
|
||||||
|
|
||||||
const Keys = new Set(selecteds);
|
const Keys = new Set(selecteds);
|
||||||
|
@ -185,4 +184,28 @@ export const drop = (info: AntTreeNodeDropEvent, treeData: any) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return data;
|
return data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 查找最深层级
|
||||||
|
export const getMaxDepth = (data: any) => {
|
||||||
|
let maxDepth = 0;
|
||||||
|
data.forEach((node: any) => {
|
||||||
|
const depth = getNodeDepth(node);
|
||||||
|
if (depth > maxDepth) {
|
||||||
|
maxDepth = depth;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return maxDepth;
|
||||||
|
};
|
||||||
|
export const getNodeDepth = (node: any) => {
|
||||||
|
let depth = 1;
|
||||||
|
if (node.children) {
|
||||||
|
node.children.forEach((child: any) => {
|
||||||
|
const childDepth = getNodeDepth(child) + 1;
|
||||||
|
if (childDepth > depth) {
|
||||||
|
depth = childDepth;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return depth;
|
||||||
|
};
|
||||||
|
|
Loading…
Reference in New Issue