464 lines
11 KiB
Vue
464 lines
11 KiB
Vue
|
<!--
|
|||
|
* @name: 弹窗配置
|
|||
|
* @author: zhangpengcheng
|
|||
|
* @date: 2022-08-25
|
|||
|
-->
|
|||
|
<template>
|
|||
|
<!-- 权限设置弹框 -->
|
|||
|
<!-- :style="{'margin':isCenter?'auto':''}"> -->
|
|||
|
<div style="padding: 16px; height: 100%">
|
|||
|
<div flex="cross:center" v-if="filterShow" style="margin-bottom: 5px">
|
|||
|
<el-input
|
|||
|
placeholder="输入关键字进行过滤"
|
|||
|
v-model="filterText"
|
|||
|
style="margin-right: 13px"
|
|||
|
></el-input>
|
|||
|
<el-button
|
|||
|
icon="el-icon-plus"
|
|||
|
style="height: 32px; line-height: 32px; padding: 0 13px !important"
|
|||
|
@click="add"
|
|||
|
v-if="filterButtonShow"
|
|||
|
>
|
|||
|
</el-button>
|
|||
|
</div>
|
|||
|
<div
|
|||
|
flex="dir:top cross:center main:center"
|
|||
|
style="margin: auto; height: calc(100% - 22px); overflow: auto"
|
|||
|
class="treeBodyHeight"
|
|||
|
>
|
|||
|
<div class="menu-i" flex="cross:center main:center">
|
|||
|
<div class="menu-i-t" flex="cross:top main:justify">
|
|||
|
<el-tree
|
|||
|
:data="menuData"
|
|||
|
:check-strictly="true"
|
|||
|
:default-checked-keys="selectData"
|
|||
|
v-loading="treeLoading"
|
|||
|
@node-click="handleNodeClick"
|
|||
|
:expand-on-click-node="false"
|
|||
|
:default-expand-all="expandAll"
|
|||
|
:filter-node-method="filterNode"
|
|||
|
:props="treeProps"
|
|||
|
style="width: 100%; background-color: transparent"
|
|||
|
@check-change="checkChange"
|
|||
|
node-key="id"
|
|||
|
ref="elTree"
|
|||
|
:show-checkbox="showCheckbox"
|
|||
|
>
|
|||
|
<div
|
|||
|
flex="cross:center main:justify"
|
|||
|
style="width: calc(100% - 31px)"
|
|||
|
slot-scope="{ node, data }"
|
|||
|
>
|
|||
|
<p
|
|||
|
class="nowrap"
|
|||
|
style="
|
|||
|
flex: 1;
|
|||
|
font-size: 12px;
|
|||
|
height: 32px;
|
|||
|
line-height: 32px;
|
|||
|
"
|
|||
|
@dblclick="dbTree(node, data)"
|
|||
|
>
|
|||
|
{{ nodeLabel == "" ? node.label : node.label[nodeLabel] }}
|
|||
|
</p>
|
|||
|
<div style="width: 60px" v-if="treeButton">
|
|||
|
<el-button
|
|||
|
type="text"
|
|||
|
size="mini"
|
|||
|
icon="el-icon-plus"
|
|||
|
v-if="appendButton"
|
|||
|
@click.stop="() => append(node, data)"
|
|||
|
>
|
|||
|
</el-button>
|
|||
|
<el-button
|
|||
|
type="text"
|
|||
|
size="mini"
|
|||
|
icon="el-icon-edit"
|
|||
|
v-if="reviseButton"
|
|||
|
@click.stop="() => revise(node, data)"
|
|||
|
>
|
|||
|
</el-button>
|
|||
|
<el-button
|
|||
|
type="text"
|
|||
|
size="mini"
|
|||
|
icon="el-icon-delete"
|
|||
|
v-if="removeButton"
|
|||
|
@click.stop="() => remove(node, data)"
|
|||
|
>
|
|||
|
</el-button>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
</el-tree>
|
|||
|
<div @click="changePcAll" class="checkText" v-if="Allshow">全选</div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
<div flex="cross:center main:center" style="width: 100%" v-if="isSaveBtn">
|
|||
|
<el-button style="width: 40%" type="primary" @click="saveMenuUser"
|
|||
|
>保存</el-button
|
|||
|
>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
</template>
|
|||
|
<script>
|
|||
|
// import { queryMenuList, menuListSave } from '@/api/apis/auth'
|
|||
|
export default {
|
|||
|
props: {
|
|||
|
// 是否默认展开所有节点
|
|||
|
expandAll: {
|
|||
|
type: Boolean,
|
|||
|
default: true,
|
|||
|
},
|
|||
|
// 操作按钮
|
|||
|
treeButton: {
|
|||
|
type: Boolean,
|
|||
|
default: false,
|
|||
|
},
|
|||
|
// 操作按钮
|
|||
|
filterButtonShow: {
|
|||
|
type: Boolean,
|
|||
|
default: false,
|
|||
|
},
|
|||
|
// 是否显示保存按钮
|
|||
|
isSaveBtn: {
|
|||
|
type: Boolean,
|
|||
|
default: false,
|
|||
|
},
|
|||
|
// 是否显示全选按钮
|
|||
|
Allshow: {
|
|||
|
type: Boolean,
|
|||
|
default: false,
|
|||
|
},
|
|||
|
// 是否显示多选按钮
|
|||
|
showCheckbox: {
|
|||
|
type: Boolean,
|
|||
|
default: false,
|
|||
|
},
|
|||
|
// 是否居中
|
|||
|
isCenter: {
|
|||
|
type: Boolean,
|
|||
|
default: true,
|
|||
|
},
|
|||
|
// 是否显示筛选
|
|||
|
filterShow: {
|
|||
|
type: Boolean,
|
|||
|
default: false,
|
|||
|
},
|
|||
|
menuData: {
|
|||
|
type: Array,
|
|||
|
default: () => {
|
|||
|
return [];
|
|||
|
},
|
|||
|
},
|
|||
|
setting: {
|
|||
|
type: Boolean,
|
|||
|
default: false,
|
|||
|
},
|
|||
|
treeLoading: {
|
|||
|
type: Boolean,
|
|||
|
default: false,
|
|||
|
},
|
|||
|
appendButton: {
|
|||
|
type: Boolean,
|
|||
|
default: true,
|
|||
|
},
|
|||
|
reviseButton: {
|
|||
|
type: Boolean,
|
|||
|
default: true,
|
|||
|
},
|
|||
|
removeButton: {
|
|||
|
type: Boolean,
|
|||
|
default: true,
|
|||
|
},
|
|||
|
nodeLabel: {
|
|||
|
type: String,
|
|||
|
default: "",
|
|||
|
},
|
|||
|
treeProps: {
|
|||
|
type: Object,
|
|||
|
default() {
|
|||
|
return {
|
|||
|
children: "children",
|
|||
|
label: "label",
|
|||
|
};
|
|||
|
},
|
|||
|
},
|
|||
|
},
|
|||
|
watch: {
|
|||
|
defaultTheme: {
|
|||
|
handler: function (val, oldVal) {
|
|||
|
this.theme = val;
|
|||
|
// document.getElementsByTagName('body')[0].style.setProperty('--active', val)
|
|||
|
|
|||
|
// let arr = document.getElementsByClassName('.el-tree-node:focus>.el-tree-node__content')
|
|||
|
// $('.el-tree-node:focus>.el-tree-node__content').css('color',val)
|
|||
|
},
|
|||
|
immediate: true,
|
|||
|
},
|
|||
|
filterText(val) {
|
|||
|
this.$refs.elTree.filter(val);
|
|||
|
},
|
|||
|
},
|
|||
|
data() {
|
|||
|
return {
|
|||
|
filterText: "",
|
|||
|
theme: "",
|
|||
|
powerDlog: false,
|
|||
|
// 回显选中ids
|
|||
|
selectData: [],
|
|||
|
// 树状图设置
|
|||
|
// treeProps: {
|
|||
|
// label: 'menuName',
|
|||
|
// children: 'id',
|
|||
|
// },
|
|||
|
// treeProps: {
|
|||
|
// children: 'children',
|
|||
|
// label: 'label'
|
|||
|
// },
|
|||
|
|
|||
|
// PC菜单全选
|
|||
|
checkedAllPc: false,
|
|||
|
// 防连点
|
|||
|
outing: false,
|
|||
|
};
|
|||
|
},
|
|||
|
created() {},
|
|||
|
mounted() {},
|
|||
|
computed: {
|
|||
|
defaultTheme() {
|
|||
|
return this.$store.state.settings.theme;
|
|||
|
},
|
|||
|
},
|
|||
|
methods: {
|
|||
|
clickFirst() {
|
|||
|
document.querySelectorAll(".is-focusable")[0].click();
|
|||
|
},
|
|||
|
setCurrentKey(selectId) {
|
|||
|
this.$nextTick(() => {
|
|||
|
this.$refs.elTree.setCurrentKey(selectId);
|
|||
|
});
|
|||
|
},
|
|||
|
dbTree(node, data) {
|
|||
|
this.setCurrentKey(null);
|
|||
|
},
|
|||
|
// 添加
|
|||
|
append(node, data) {
|
|||
|
this.$emit("append", data);
|
|||
|
},
|
|||
|
// 编辑
|
|||
|
revise(node, data) {
|
|||
|
this.$emit("revise", data);
|
|||
|
},
|
|||
|
// 删除
|
|||
|
remove(node, data) {
|
|||
|
this.$emit("remove", data);
|
|||
|
},
|
|||
|
add() {
|
|||
|
this.$emit("add");
|
|||
|
},
|
|||
|
filterNode(value, data, node) {
|
|||
|
if (!value) return true;
|
|||
|
let nodeData =
|
|||
|
this.nodeLabel == ""
|
|||
|
? data[this.treeProps.label]
|
|||
|
: data[this.treeProps.label][this.nodeLabel];
|
|||
|
return nodeData.indexOf(value) !== -1;
|
|||
|
},
|
|||
|
buttonL(el) {
|
|||
|
el.active = !el.active;
|
|||
|
this.$forceUpdate();
|
|||
|
},
|
|||
|
setData(id) {
|
|||
|
this.selectData.push(id);
|
|||
|
},
|
|||
|
saveMenuUser() {
|
|||
|
let allKeys = this.getKey();
|
|||
|
this.$emit("onSaveMenu", allKeys);
|
|||
|
},
|
|||
|
// 获取选中的key值
|
|||
|
getKey() {
|
|||
|
return this.$refs.elTree.getCheckedKeys();
|
|||
|
},
|
|||
|
// 初始数据
|
|||
|
initData() {
|
|||
|
// 菜单数据
|
|||
|
// this.menuData = [];
|
|||
|
|
|||
|
// 回显选中ids
|
|||
|
this.selectData = [];
|
|||
|
},
|
|||
|
// 关闭弹窗
|
|||
|
handleClose() {
|
|||
|
this.powerDlog = false;
|
|||
|
this.initData();
|
|||
|
},
|
|||
|
// 全选、反选
|
|||
|
changePcAll() {
|
|||
|
this.checkedAllPc = !this.checkedAllPc;
|
|||
|
let selectData = [];
|
|||
|
if (this.checkedAllPc) {
|
|||
|
selectData = this.cycleData(this.menuData);
|
|||
|
}
|
|||
|
this.selectData = selectData;
|
|||
|
},
|
|||
|
/**
|
|||
|
* @description 递归获取菜单id(树状 多叉树结构)
|
|||
|
* @author duanyipeng
|
|||
|
* @createDate 2020/7/31 20:54
|
|||
|
* @param {Array} outData 需要递归的数组
|
|||
|
* @param {Boolean} isSelect: false返回所有id,true返回已选择id
|
|||
|
*/
|
|||
|
cycleData(outData, isSelect) {
|
|||
|
let newData = [];
|
|||
|
|
|||
|
function cycle(data) {
|
|||
|
if (!data || data.length == 0) {
|
|||
|
return false;
|
|||
|
} else {
|
|||
|
for (var i = 0, len = data.length; i < len; i++) {
|
|||
|
let item = data[i];
|
|||
|
if (isSelect && item.selected == 1) {
|
|||
|
newData.push(item.id);
|
|||
|
}
|
|||
|
if (!isSelect) {
|
|||
|
newData.push(item.id);
|
|||
|
}
|
|||
|
cycle(item.id);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
cycle(outData);
|
|||
|
return newData;
|
|||
|
},
|
|||
|
getData(childIds) {
|
|||
|
let newData = [];
|
|||
|
|
|||
|
function cycle(data) {
|
|||
|
data.forEach((el) => {
|
|||
|
childIds.forEach((item) => {
|
|||
|
if (el.id == item) {
|
|||
|
newData.push(el);
|
|||
|
}
|
|||
|
});
|
|||
|
if (el.children != null && el.children && el.children.length) {
|
|||
|
cycle(el.children, childIds);
|
|||
|
}
|
|||
|
});
|
|||
|
}
|
|||
|
cycle(this.menuData, childIds);
|
|||
|
return newData;
|
|||
|
},
|
|||
|
/**
|
|||
|
* @description 节点选中状态发生变化时的回调
|
|||
|
* @author duanyipeng
|
|||
|
* @createDate 2020/7/31 20:53
|
|||
|
* @param { Object } nodeDode 当前节点对象
|
|||
|
* @param { Boolean } checked 当前节点是否选中
|
|||
|
*/
|
|||
|
checkChange(nodeDode, checked) {
|
|||
|
let getHalfCheckedKeys = this.$refs.elTree
|
|||
|
.getCheckedKeys()
|
|||
|
.concat(this.$refs.elTree.getHalfCheckedKeys());
|
|||
|
// let getHalfCheckedKeys = this.$refs.elTree.getHalfCheckedKeys()
|
|||
|
let childIds =
|
|||
|
getHalfCheckedKeys.length != 0 ? getHalfCheckedKeys : this.selectData;
|
|||
|
let checkdata = this.getData(childIds);
|
|||
|
this.$emit("checkChange", childIds, checkdata);
|
|||
|
return;
|
|||
|
let id = nodeDode.id;
|
|||
|
// let childIds = this.cycleData(id)
|
|||
|
// 循环设置子项是否选中
|
|||
|
childIds.forEach((item) => {
|
|||
|
this.$refs.elTree.setChecked(item, checked);
|
|||
|
});
|
|||
|
},
|
|||
|
// 点击事件
|
|||
|
handleNodeClick(data) {
|
|||
|
this.$emit("handleNodeClick", data);
|
|||
|
},
|
|||
|
},
|
|||
|
};
|
|||
|
</script>
|
|||
|
<style lang="scss">
|
|||
|
// $activeColor:val(--activeColor, "#00aaff");
|
|||
|
.nowrap {
|
|||
|
/*让长段文本不换行*/
|
|||
|
white-space: nowrap;
|
|||
|
/*设置文本超出元素宽度部分隐藏*/
|
|||
|
overflow-x: hidden;
|
|||
|
/*设置文本超出部分用省略号显示*/
|
|||
|
text-overflow: ellipsis;
|
|||
|
}
|
|||
|
|
|||
|
.el-tree-node__content {
|
|||
|
height: 32px !important;
|
|||
|
}
|
|||
|
|
|||
|
.el-tree-node__label {
|
|||
|
// font-size: 16px !important;
|
|||
|
margin-left: 4px;
|
|||
|
}
|
|||
|
|
|||
|
.el-tree-node__content > label.el-checkbox {
|
|||
|
transform: scale(1.3);
|
|||
|
}
|
|||
|
|
|||
|
.el-tree-node__content > .el-tree-node__expand-icon {
|
|||
|
font-size: 18px;
|
|||
|
}
|
|||
|
|
|||
|
.el-checkbox__label {
|
|||
|
font-size: 16px;
|
|||
|
}
|
|||
|
|
|||
|
.checkBox .el-checkbox__inner {
|
|||
|
transform: scale(1.3);
|
|||
|
}
|
|||
|
</style>
|
|||
|
<style lang="scss" scoped>
|
|||
|
.el-tree-node.is-current > .el-tree-node__content .el-button--text {
|
|||
|
color: white;
|
|||
|
}
|
|||
|
|
|||
|
.menu-i {
|
|||
|
width: 100%;
|
|||
|
// margin-bottom: 24px;
|
|||
|
height: 100%;
|
|||
|
|
|||
|
&-f {
|
|||
|
color: #52575a;
|
|||
|
font-size: 18px;
|
|||
|
text-align: center;
|
|||
|
margin-bottom: 12px;
|
|||
|
}
|
|||
|
|
|||
|
&-t {
|
|||
|
width: 100%;
|
|||
|
height: 100%;
|
|||
|
// height: 450px;
|
|||
|
// border: 1px solid #d8d8d8;
|
|||
|
// overflow-y: auto;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
.checkBox {
|
|||
|
margin-top: 6px;
|
|||
|
margin-right: 12px;
|
|||
|
}
|
|||
|
|
|||
|
.checkText {
|
|||
|
width: 60px;
|
|||
|
height: 30px;
|
|||
|
line-height: 30px;
|
|||
|
text-align: center;
|
|||
|
color: #333;
|
|||
|
font-size: 16px;
|
|||
|
cursor: pointer;
|
|||
|
transition: all 0.3s ease-in-out;
|
|||
|
|
|||
|
&:hover {
|
|||
|
color: #ecf5ff;
|
|||
|
}
|
|||
|
}
|
|||
|
</style>
|