Files
dyf-vue-ui/src/views/fys-equipment/group/index.vue
2025-09-03 14:16:47 +08:00

1143 lines
25 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="content" >
<div class="leftTree fleft">
<div class="head">
<div class="title">设备分组</div>
<div class="nodeEdit" @click="addNode(null)">新增</div>
</div>
<div class="Search">
<input type="text" class="txt" v-model="searchTxt" placeholder="输入分组名称" />
</div>
<div class="treeContent">
<el-tree :data="treeData" :props="defaultProps" accordion @node-click="handleNodeClick">
<template #default="{ node, data }">
<div class="custom-tree-node" :class="checkNode.val == data.id ? 'active' : ''">
<span :class="data.parentId != null ? '' : 'treeBold'">{{ node.label }}</span>
<div class="iconContent">
<Edit class="icon" @click.stop="editNode(node)" />
<Plus class="icon" @click.stop="addNode(node)" />
<Delete class="icon red" @click.stop="delNode(node)" />
</div>
</div>
</template>
</el-tree>
</div>
</div>
<div class="main fleft">
<div class="toolBar">
<div class="btnAdd" @click="showDevice">
<Plus class="icon" style="width: 14px;height: 14px;" />
添加设备
</div>
<div class="rightSearch">
<div class="searchContent">
<div class="center H100">
<input type="text" class="serchTxt" v-model="GjSearchForm.deviceName" @input="InputSearch()" />
<Search class="icon" style="width: 16px;height:16px;" />
</div>
</div>
<div class="gjSearch" @click="ToggleGjSearch()">高级筛选</div>
</div>
</div>
<div class="searchBar" :class="Status.isGjSearch ? '' : 'displayNone'">
<div style="margin-top:20px;">
<el-form class="demo-form-inline" :inline="true" :model="GjSearchForm" label-width="auto"
style="width: 100%;">
<el-form-item label="设备类型">
<el-select v-model="GjSearchForm.deviceType" placeholder="请选择">
<el-option v-for="item in deviceTypes" :key="item.value" :label="item.typeName" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item label="通信方式">
<el-select v-model="GjSearchForm.netMode" placeholder="请选择">
<el-option label="4G" :value="0" />
<el-option label="蓝牙" :value="1" />
</el-select>
</el-form-item>
<el-form-item>
<div class="btnSearch" @click="getDeviceList()">查询</div>
<div class="btnReset" @click="ResetQuery()">重置</div>
</el-form-item>
</el-form>
</div>
</div>
<div class="grid">
<el-card shadow="hover">
<div class="gridTool">
<div class="button-row">
<el-button type="success" @click="showCheckGroup('check')" plain>移动</el-button>
<el-button type="danger" plain @click="groupDelDevice()">删除</el-button>
</div>
</div>
<el-table ref="grid" height="calc(100vh - 320px)" v-loading="Status.loading" border :data="deviceList"
@selection-change="RowSelectionChange">
<el-table-column type="selection" width="50" align="center" />
<el-table-column label="设备名称" align="center" prop="deviceName" />
<el-table-column prop="devicePic" label="设备图片">
<template #default="scope">
<el-popover placement="right" trigger="click">
<template #reference>
<img :src="scope.row.devicePic"
style="width: 40px; height: 40px; cursor: pointer; object-fit: contain"
class="hover:opacity-80 transition-opacity" />
</template>
<img :src="scope.row.devicePic" style="max-width: 600px; max-height: 600px; object-fit: contain" />
</el-popover>
</template>
</el-table-column>
<el-table-column prop="typeName" label="设备类型" />
<el-table-column prop="bindingStatus" label="绑定状态">
<template #default="scope">
<el-tag :type="scope.row.bindingStatus === 1 ? 'success' : 'info'">
{{ scope.row.bindingStatus === 1 ? '已绑定' : '未绑定' }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" fixed="right" width="280" class-name="small-padding fixed-width">
<template #default="scope">
<div class="center">
<div class="moveDev" @click="showCheckGroup('item', scope.row)">移动</div>
<div class="delDev" @click="groupDelDevice(scope.row)">删除</div>
</div>
</template>
</el-table-column>
</el-table>
<pagination v-show="pagin.total > 0" v-model:page="GjSearchForm.pageNum" v-model:limit="GjSearchForm.pageSize"
:total="pagin.total" @pagination="getDeviceList" />
</el-card>
</div>
</div>
<div class="clear"></div>
<!-- 提示框 -->
<el-dialog :width="300" :draggable="true" v-model="Status.confirm.Visible" :title="Status.confirm.title" width="500" center>
<span>
{{ Status.confirm.text }}
</span>
<template #footer>
<div class="dialog-footer">
<el-button v-show="Status.confirm.showCancel" @click="Status.confirm.cancelCallback">取消</el-button>
<el-button type="primary" @click="Status.confirm.OkCallback">
确定
</el-button>
</div>
</template>
</el-dialog>
<!-- 选择分组的弹窗 -->
<el-dialog v-model="Status.dialogGroupVisible" title="选择分组" width="500" :draggable="true">
<el-tree :data="treeData" :props="defaultProps" accordion>
<template #default="{ node, data }">
<div class="custom-tree-node" @click.stop="CheckGroup(data)">
<span :class="data.parentId != null ? '' : 'treeBold'">{{ node.label }}</span>
<span>选择</span>
</div>
</template>
</el-tree>
<el-button type="primary" @click="OkCheckGroup()">
确定
</el-button>
<el-button type="primary" @click="CancelCheckGroup()">
取消
</el-button>
</el-dialog>
<!-- 选择设备的穿梭框 -->
<el-dialog v-model="Status.dialogDeviceVisible" title="选择设备" width="800" :draggable="true">
<el-transfer :titles="['所有设备', '已选择设备']" v-model="transfer.value" :data="transfer.data" :filterable="true" />
<div class="center" style="margin-top: 10px;">
<el-button type="primary" @click="OKCheckDevice()">
确定
</el-button>
<el-button type="info" @click="hideDevice()">
取消
</el-button>
</div>
</el-dialog>
</div>
</template>
<script setup lang="ts">
import api from '@/api/equipmentManagement/devicegroup/index';
import common from '@/utils/common'
interface Device {
deviceName: string;
devicePic: string;
typeName: string;
bindingStatus: string;
}
var searchTxt = ref(''); //左侧树筛选文本
var treeDataOrin = ref([]); //树控件的数据源
var grid = ref(null);
var cEdit = ref({ val: "", txt: "" });//当前正在编辑的节点数据
var checkNode = { val: '' };//记录被选中的节点
//全局状态控制
var Status = reactive({
isEditTreeNode: false,//是否编辑节点
isGjSearch: false,//是否显示高级筛选
loading: false,
confirm: {
Visible: false,
title: '',
text: '',
cancelCallback: '',
OkCallback: '',
showCancel: true
},
dialogGroupVisible: false,//是否显示选择分组的弹窗
dialogDeviceVisible: false//是否显示选择设备的弹窗
});
//页码控件数据
var pagin = reactive({
total: 0,
});
//右边的筛选条件
var GjSearchForm = reactive({
deviceName: '',
deviceType: "",
netMode: "",
pageNum: 1,
pageSize: 10
});
//设备列表
var deviceList = ref<Device[]>();
//所有设备类型
var deviceTypes = reactive([]);
//穿梭框的数据和值
var transfer = reactive({
value: [],
data: []
});
window.confirm = function (text, OK, cancel, title) {
let Cfg = {
Visible: true,
title: '提示',
text: text ? text : '此操作不可逆,您确定这样做吗?',
OkCallback: () => {
Status.confirm.Visible = false;
if (OK) {
OK();
}
},
showCancel: true,
cancelCallback: () => {
Status.confirm.Visible = false;
if (cancel) {
cancel();
}
}
}
Status.confirm = Cfg;
}
window.alert = function (text, OK, title) {
let Cfg = {
Visible: true,
title: title ? title : '提示',
text: text ? text : '不符合规则',
OkCallback: () => {
Status.confirm.Visible = false;
if (OK) {
OK();
}
},
showCancel: false,
cancelCallback: null
}
Status.confirm = Cfg;
}
var hideConfirm = function () {
let Cfg = {
Visible: false,
title: '提示',
text: "",
cancelCallback: null,
OkCallback: null
}
Status.confirm = Cfg;
}
var showloading = function () {
// window.loadingIndex = ElLoading.service({ fullscreen: true })
Status.loading=true;
}
var closeLoading = function () {
// if (window.loadingIndex) {
// window.loadingIndex.close();
// }
Status.loading=false;
}
var hideloading = closeLoading;
function ResetQuery() {
GjSearchForm.deviceType = "";
GjSearchForm.netMode = "";
}
//查询某个节点的设备
var getDeviceList = () => {
if (!checkNode.val) {
pagin.total = 0;
deviceList.value = [];
return;
}
let para = {
nodeCode: checkNode.val,
pageIndex: GjSearchForm.pageNum,
pageSize: GjSearchForm.pageSize,
communicationMode: GjSearchForm.netMode,
deviceType: GjSearchForm.deviceType,
deviceName: GjSearchForm.deviceName
}
showloading();
api.getNodeDevice(para).then((res) => {
deviceList.value = res.rows;
pagin.total = res.total;
}).catch((ex) => {
console.log("出现了异常", ex);
}).finally(() => {
hideloading();
});
}
//树控件节点点击事件
var handleNodeClick = (node) => {
if (checkNode.val == node.id) {
return;
}
console.log("节点数据:", node.id);
checkNode.val = node.id;
getDeviceList();
}
//树控件筛选后显示的数据源
var treeData = computed(() => {
let arr = api.treeNodeSearch(treeDataOrin.value, searchTxt.value, 'groupName', 'children');
return arr;
});
//显示/隐藏高级筛选
var ToggleGjSearch = function () {
Status.isGjSearch = !Status.isGjSearch;
}
//编辑节点
var editNode = (node) => {
console.log("编辑节点:", node.data.value);
cEdit.value.val = node.data.id;
cEdit.value.txt = node.data.groupName;
Status.isEditTreeNode = true;
ElMessageBox.prompt('请输入名称', '编辑分组', {
confirmButtonText: '确认',
cancelButtonText: '取消',
inputValue: node.data.groupName
})
.then(({ value }) => {
cEdit.value.txt = value;
completeEdit(node);
});
//
}
//完成编辑
var completeEdit = (node) => {
let now =common.DateFormat(new Date(), "yyyy-MM-dd HH:mm:ss");
let newNode =
{
"createDept": node.data.createDept,//创建部门
"createBy": node.data.createBy,//创建者
"createTime": now,//创建时间
"updateBy": node.data.updateBy,//更新者
"updateTime": now,//更新时间
"params": {
"additionalProp1": "",
"additionalProp2": "",
"additionalProp3": ""
},
"id": node.data.id,//主键ID
"groupName": cEdit.value.txt,//分组名称
"status": 1,//状态0-禁用1-正常
"parentId": node.data.parentId,//父分组ID
"fullPath": node.data.fullPath,//完整分组路径
"isDeleted": 0//删除标记0-未删除1-已删除
};
showloading();
api.updateTreeName(treeDataOrin.value, newNode, cEdit.value.txt).then((res) => {
if (res.code == 200) {
alert("操作成功");
RefreshTree();
} else {
alert(res.msg);
}
}).finally(() => {
hideloading();
});
Status.isEditTreeNode = false;
}
//放弃编辑
var cancelEdit = (node) => {
cEdit.value.val = "";
cEdit.value.txt = "";
Status.isEditTreeNode = false;
}
//删除节点
var delNode = (node) => {
if (node.data.children && node.data.children.length > 0) {
alert("节点包含子节点,不允许删除");
return;
}
confirm("您确认删除’" + node.data.groupName + "’节点吗", () => {
hideConfirm();
api.delTreeNode(treeDataOrin.value, node.data.id).then((res) => {
if (res.code == 200) {
alert("操作成功");
RefreshTree();
} else {
alert(res.msg);
}
});
}, () => {
hideConfirm();
});
}
//增加节点
var addNode = (node) => {
let title = '';
if (node) {
console.log("给节点新增子节点:", node.data.id);
title = '添加子节点';
}
else {
console.log("新增初级节点")
title = '添加根节点'
}
let val = new Date().getTime();
// let newNode = { value: val, txt: '' };
let now =common.DateFormat(new Date(), "yyyy-MM-dd HH:mm:ss");
ElMessageBox.prompt('请输入名称', title, {
confirmButtonText: '确认',
cancelButtonText: '取消'
})
.then(({ value }) => {
if (!value) {
alert("请输入分组名称");
return;
}
let newNode =
{
"createDept": 0,//创建部门
"createBy": 0,//创建者
"createTime": now,//创建时间
"updateBy": 0,//更新者
"updateTime": now,//更新时间
"params": {
"additionalProp1": "",
"additionalProp2": "",
"additionalProp3": ""
},
"id": null,//主键ID
"groupName": value,//分组名称
"status": 1,//状态0-禁用1-正常
"parentId": node ? node.data.id : null,//父分组ID
"fullPath": val,//完整分组路径
"isDeleted": 0,//删除标记0-未删除1-已删除
};
showloading();
api.addTreeNode(treeDataOrin.value, newNode, node ? node.data.id : null).then((res) => {
if (res.code == 200) {
alert("操作成功");
RefreshTree();
} else {
alert(res.msg);
}
}).catch((ex) => {
console.log("ex=", ex);
}).finally(() => {
hideloading();
});
});
}
//树控件的自定义属性
var defaultProps = {
children: 'children',
label: 'groupName',
parentId: "parentId"
}
var RowSelectionChange = (tr) => {
console.log("行选中变化", tr);
getSelectionRows();
};
var getSelectionRows = () => {
if (grid.value) { // 检查ref是否已正确引用组件实例
var selectedRows = grid.value.getSelectionRows(); // 获取选中行数据数组
return selectedRows;
}
return [];
}
var RefreshTree = function () {
api.getTreeData(searchTxt.value).then((res) => {
treeDataOrin.value = res;
});
}
//从分组中删除设备
var groupDelDevice = (row) => {
let rows = [];//
if (!row) {
rows = getSelectionRows();
} else {
rows = [row];
}
if (rows.length == 0) {
alert("请选择要删除的设备");
return;
}
confirm("此操作不可逆,您确认要进行吗?", () => {
showloading();
let ids = rows.map(r => r.deviceId).join(",");
api.groupDelDevice(checkNode.val, ids).then((res) => {
if (res.code == 200) {
alert("操作成功");
getDeviceList();
} else {
alert(res.msg);
}
}).finally(() => {
hideloading();
});
}, null, "警告");
}
var showDevice = () => {
Status.dialogDeviceVisible = true;
//获取所有
let promise1 = api.getNodeDevice({
pageIndex: 1,
pageSize: 9999,
nodeCode: ""
});
//获取已选中的
let promise2 = api.getNodeDevice({
pageIndex: 1,
pageSize: 9999,
nodeCode: checkNode.val
});
cGroupAndDevice.deviceIds = [];
transfer.value = [];
Promise.allSettled([promise1, promise2]).then(res => {
if (res[0].status == 'fulfilled') {
let res1 = res[0].value;
if (res1.code == 200) {
let arr = res1.rows.map(item => ({
key: item.deviceId,
label: item.deviceName//,
// disabled: item.groupId && item.groupId == checkNode.val ? false : item.groupId ? true : false
}));
transfer.data = arr;
}
}
if (res[1].status == 'fulfilled') {
let res2 = res[1].value;
if (res2.code == 200) {
let vals = res2.rows.map(item => item.deviceId);
transfer.value = vals;
}
}
});
}
//确认选择这些设备
var OKCheckDevice = () => {
let arr = transfer.value.map(item => ({
deviceId: item
}));
if (arr.length == 0) {
alert("未选择任何设备");
return;
}
hideDevice();
cGroupAndDevice.deviceIds = arr;
cGroupAndDevice.groupid = checkNode.val;
deviceMoveGroup(cGroupAndDevice.groupid, cGroupAndDevice.deviceIds);
}
//隐藏选择设备
var hideDevice = () => {
Status.dialogDeviceVisible = false;
}
var cGroupAndDevice = {
groupid: '',
deviceIds: []
};
//显示选择分组
var showCheckGroup = (type, row) => {
let rows = [row];
if (type == 'check') {
rows = getSelectionRows();
}
if (rows.length == 0) {
alert("请选择要移动的设备");
return;
}
cGroupAndDevice.deviceIds = rows;
Status.dialogGroupVisible = true;
cGroupAndDevice.groupid = "";
}
//选中了某个分组
var CheckGroup = (item) => {
cGroupAndDevice.groupid = item.id;
}
//确定选中某个分组
var OkCheckGroup = () => {
if (!cGroupAndDevice.groupid) {
alert("请先选择分组");
return;
}
CancelCheckGroup();
deviceMoveGroup(cGroupAndDevice.groupid, cGroupAndDevice.deviceIds);
}
//隐藏选择分组
var CancelCheckGroup = () => {
Status.dialogGroupVisible = false
}
//将设备移动至分组
var deviceMoveGroup = (groupid, row) => {
let rows = [];//
if (!row) {
rows = getSelectionRows();
} else {
if (Array.isArray(row)) {
rows = row;
} else {
rows = [row];
}
}
if (rows.length == 0) {
alert("请选择要移动的设备");
return;
}
// confirm("此操作不可逆,您确认要进行吗?", () => {
showloading();
let ids = rows.map(r => r.deviceId).join(",");
api.deviceMoveGroup(groupid, ids).then((res) => {
if (res.code == 200) {
alert("操作成功");
getDeviceList();
} else {
alert(res.msg);
}
}).finally(() => {
hideloading();
});
// }, null, "警告");
}
let timer;
function InputSearch() {
clearTimeout(timer);
// 等待 500ms 无输入后执行查询
timer = setTimeout(() => {
getDeviceList();
}, 500);
}
onMounted(() => {
RefreshTree();
api.getDeviceTypeAll().then((res) => {
if (res.code == 200) {
deviceTypes = res.data.map(item => ({
value: item.deviceTypeId,
typeName: item.typeName
}))
}
});
});
</script>
<style lang="scss" scoped>
.main .searchBar .btnReset {
width: 76px;
height: 32px;
border-radius: 4px;
background-color: #00000000;
color: #027CFB;
text-align: center;
font-family: Microsoft YaHei;
font-size: 14px;
font-weight: 400;
line-height: 32px;
letter-spacing: 0px;
border: 1px solid rgb(2, 124, 251);
cursor: pointer;
}
.main .searchBar .btnSearch {
/* 组合 454 */
width: 76px;
height: 32px;
border-radius: 4px;
background-color: #027CFB;
color: #FFFFFF;
text-align: center;
font-family: Microsoft YaHei;
font-size: 14px;
font-weight: 400;
line-height: 32px;
letter-spacing: 0px;
border: none;
margin-right: 15px;
cursor: pointer;
}
.main .searchBar {
width: 100%;
height: 50px;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
align-content: center;
justify-content: space-between;
align-items: center;
}
.main .toolBar .rightSearch {
width: 295px;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
align-content: center;
justify-content: space-between;
align-items: center;
}
.main .toolBar .gjSearch {
/* 矩形 155 */
width: 85px;
height: 32px;
box-sizing: border-box;
border: 1px solid rgba(2, 124, 251, 1);
border-radius: 4px;
color: rgba(2, 124, 251, 1);
cursor: pointer;
font-family: Noto Sans SC;
font-size: 14px;
font-weight: 400;
line-height: 32px;
letter-spacing: 0px;
text-align: center;
}
.main .toolBar .searchContent {
width: 200px;
height: 32px;
border: 1px solid rgba(189, 198, 215, 1);
border-radius: 4px;
}
.main .toolBar .serchTxt {
border: none;
width: 175px;
height: 100%;
}
.main .toolBar .btnAdd {
background-color: #027CFB;
color: #FFFFFF;
width: 105px;
height: 32px;
text-align: center;
font-family: Microsoft YaHei;
font-size: 14px;
font-weight: 400;
line-height: 32px;
letter-spacing: 0px;
cursor: pointer;
}
.main .toolBar {
width: 100%;
height: 35px;
overflow: hidden;
box-sizing: border-box;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
align-content: center;
justify-content: space-between;
align-items: flex-start;
border-bottom: 1px solid rgba(235, 238, 248, 1);
}
.nodeInput {
height: 30px;
line-height: 30px;
border: 1px solid rgb(189, 198, 215);
border-radius: 4px;
box-sizing: border-box;
}
.red {
color: #FF0000;
}
.green {
color: #0ed50e;
}
.custom-tree-node {
width: 100%;
height: 40px;
line-height: 40px;
display: flex;
flex-direction: row;
align-content: center;
flex-wrap: nowrap;
justify-content: space-between;
align-items: center;
}
.custom-tree-node.active {
background: rgba(228, 234, 240, 0.4) !important;
}
.custom-tree-node .iconContent {
width: 60px;
height: 100%;
box-sizing: border-box;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
align-content: center;
justify-content: space-evenly;
align-items: center;
}
.custom-tree-node .iconContent .icon {
width: 18px;
height: 18px;
visibility: hidden;
}
.custom-tree-node-Edit .iconContent .icon {
visibility: visible !important;
}
.custom-tree-node:hover .iconContent .icon {
visibility: visible;
}
.leftTree .treeBold {
font-weight: 700;
}
.leftTree .treeContent::-webkit-scrollbar {
display: none;
}
.leftTree .treeContent {
margin-top: 10px;
height: calc(100% - 95px);
overflow: scroll;
box-sizing: border-box;
}
.leftTree .Search .txt::placeholder {
color: rgba(189, 198, 215, 1);
font-family: Microsoft YaHei;
font-size: 14px;
font-weight: 400;
letter-spacing: 0px;
text-align: left;
}
.leftTree .Search .txt {
width: 100%;
height: 100%;
border: none;
background-color: #00000000;
text-indent: 5px;
line-height: 36px;
color: rgb(96, 98, 102);
}
.leftTree .Search {
width: 100%;
margin-top: 10px;
height: 36px;
border: 1px solid rgba(189, 198, 215, 1);
border-radius: 4px;
box-sizing: border-box;
}
.leftTree .head .nodeEdit {
color: rgba(2, 124, 251, 1);
cursor: pointer;
font-family: Microsoft YaHei;
font-size: 14px;
font-weight: 400;
line-height: 18px;
letter-spacing: 0px;
text-align: left;
}
.leftTree .head .title {
color: rgba(56, 64, 79, 1);
font-family: Microsoft YaHei;
font-size: 14px;
font-weight: 700;
line-height: 18px;
letter-spacing: 0px;
text-align: left;
}
.leftTree .head {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
align-content: center;
justify-content: space-between;
align-items: center;
width: 100%;
height: 40px;
border-bottom: 1px solid rgba(235, 238, 248, 1);
}
.fleft {
float: left;
}
.fright {
float: right;
}
.clear {
clear: both;
}
.center {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
align-content: center;
align-items: center;
justify-content: center;
}
.displayNone {
display: none !important;
}
input:focus {
outline: none;
}
.H100 {
height: 100%;
}
.content {
width: 100%;
min-height: calc(100vh - 84px);
height: calc(100vh - 84px);
background-color: #FFFFFF;
font-size: 16px;
box-sizing: border-box;
padding: 8px 20px;
font-family: 'Microsoft YaHei';
}
.leftTree {
width: 18%;
height: 100%;
border-radius: 4px;
box-shadow: 0px 0px 6px 0px rgba(0, 34, 96, 0.1);
background: rgba(255, 255, 255, 1);
margin-right: 15px;
box-sizing: border-box;
padding: 12px 13px;
}
.main {
width: calc(82% - 15px);
height: 100%;
border-radius: 4px;
box-shadow: 0px 0px 6px 0px rgba(0, 34, 96, 0.1);
background: rgba(255, 255, 255, 1);
box-sizing: border-box;
padding: 15px;
}
.moveDev {
margin-right: 10px;
color: rgba(2, 124, 251, 1);
font-family: Noto Sans SC;
font-size: 12px;
font-weight: 400;
letter-spacing: 0px;
}
.delDev {
color: rgba(224, 52, 52, 1);
font-family: Noto Sans SC;
font-size: 12px;
font-weight: 400;
letter-spacing: 0px;
}
.gridTool {
padding-bottom: 10px;
}
:deep .el-tree-node__content {
height: auto !important;
}
</style>