|
|
|
|
|
<!--
|
|
|
|
|
|
图件的图层树
|
|
|
|
|
|
|
|
|
|
|
|
add by RYG
|
|
|
|
|
|
-->
|
|
|
|
|
|
<template>
|
|
|
|
|
|
<div class="tree-component">
|
|
|
|
|
|
<!-- 加载状态(由父组件控制) -->
|
|
|
|
|
|
<div v-if="loading" class="loading">
|
|
|
|
|
|
加载中……
|
|
|
|
|
|
<!-- <el-skeleton :rows="3" animated /> -->
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div v-else class="tree-container">
|
|
|
|
|
|
<div class="operation" v-if="!props.isPopup">
|
|
|
|
|
|
<el-button
|
|
|
|
|
|
v-for="(btn, index) in iconButtons"
|
|
|
|
|
|
:key="index"
|
|
|
|
|
|
class="square-icon-button"
|
|
|
|
|
|
:icon="getNodeIcon(btn.id)"
|
|
|
|
|
|
:type="btn.type"
|
|
|
|
|
|
:title="btn.title"
|
|
|
|
|
|
text
|
|
|
|
|
|
@click="() => setLayerStatus(btn.id)"
|
|
|
|
|
|
/>
|
|
|
|
|
|
<el-divider direction="vertical" />
|
|
|
|
|
|
<el-button
|
|
|
|
|
|
class="square-icon-button"
|
|
|
|
|
|
:icon="Delete"
|
|
|
|
|
|
type="danger"
|
|
|
|
|
|
circle
|
|
|
|
|
|
title="删除"
|
|
|
|
|
|
text
|
|
|
|
|
|
@click="deleteLayer"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<!-- 树形结构(使用外部传入的数据) -->
|
|
|
|
|
|
<el-tree
|
|
|
|
|
|
ref="treeRef"
|
|
|
|
|
|
v-model="selectedKeys"
|
|
|
|
|
|
:data="treeData"
|
|
|
|
|
|
show-checkbox
|
|
|
|
|
|
node-key="id"
|
|
|
|
|
|
default-expand-all
|
|
|
|
|
|
:highlight-current="true"
|
|
|
|
|
|
:props="defaultProps"
|
|
|
|
|
|
placeholder="点击展开加载子节点..."
|
|
|
|
|
|
clearable
|
|
|
|
|
|
@check="handleCheck"
|
|
|
|
|
|
class="custom-tree"
|
|
|
|
|
|
>
|
|
|
|
|
|
<template #default="{ node, data }">
|
|
|
|
|
|
<div class="tree-node">
|
|
|
|
|
|
<span class="icon-container">
|
|
|
|
|
|
<!-- <el-icon :size="treeConfig.iconSize" :class="'icon-orange'">
|
|
|
|
|
|
<component :is="data.icon" />
|
|
|
|
|
|
</el-icon> -->
|
|
|
|
|
|
<el-icon
|
|
|
|
|
|
v-if="data.status"
|
|
|
|
|
|
:size="treeConfig.iconSize"
|
|
|
|
|
|
:class="'icon-orange'"
|
|
|
|
|
|
>
|
|
|
|
|
|
<component :is="getNodeIcon(data.status)" />
|
|
|
|
|
|
</el-icon>
|
|
|
|
|
|
</span>
|
|
|
|
|
|
<span>{{ node.label }}</span>
|
|
|
|
|
|
<!-- <span v-if="data.count" class="node-count">{{ data.count }}</span> -->
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</el-tree>
|
|
|
|
|
|
<div class="popup-operation" v-if="props.isPopup">
|
|
|
|
|
|
<el-button :icon="Finished" @click="handleConfirm" type="primary">确定</el-button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<!-- 操作按钮 -->
|
|
|
|
|
|
<!-- <div class="actions" v-if="treeData.length">
|
|
|
|
|
|
<el-button type="primary" @click="getSelectedNodes">获取选中项</el-button>
|
|
|
|
|
|
<el-button @click="clearSelection">清空选择</el-button>
|
|
|
|
|
|
</div> -->
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script setup>
|
|
|
|
|
|
import { ref, onMounted } from "vue";
|
|
|
|
|
|
import { emitter } from "@/utils/eventBus";
|
|
|
|
|
|
import { ElTree, ElSkeleton, ElButton } from "element-plus";
|
|
|
|
|
|
import { Hide, Lock, Edit, Delete, Finished } from "@element-plus/icons-vue";
|
|
|
|
|
|
import { useRoute } from 'vue-router';
|
|
|
|
|
|
|
|
|
|
|
|
const route = useRoute();
|
|
|
|
|
|
|
|
|
|
|
|
const { message, status, send } = useWebSocket();
|
|
|
|
|
|
|
|
|
|
|
|
const props = defineProps({
|
|
|
|
|
|
isPopup: { type: Boolean, default: false },
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
const isPopup = computed(() => {
|
|
|
|
|
|
return props.isPopup;
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
const iconButtons = [
|
|
|
|
|
|
{ icon: "edit", title: "可编辑", type: "warning", id: 1 },
|
|
|
|
|
|
{ icon: "lock", title: "只读", type: "warning", id: 2 },
|
|
|
|
|
|
{ icon: "hide", title: "隐藏", type: "warning", id: 3 },
|
|
|
|
|
|
// { icon: Delete, title: "删除", type: "danger" },
|
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
|
|
// 树配置
|
|
|
|
|
|
const treeConfig = ref({
|
|
|
|
|
|
fontSize: 13,
|
|
|
|
|
|
iconSize: 13,
|
|
|
|
|
|
nodeHeight: 25,
|
|
|
|
|
|
currentHighlight: true,
|
|
|
|
|
|
showIcons: true,
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 树的数据
|
|
|
|
|
|
const treeData = ref([]);
|
|
|
|
|
|
// 加载状态
|
|
|
|
|
|
const loading = ref(true);
|
|
|
|
|
|
// 得到的原始图层数据
|
|
|
|
|
|
const sourceData = ref([]);
|
|
|
|
|
|
// 响应式数据
|
|
|
|
|
|
const treeRef = ref(null);
|
|
|
|
|
|
// 选中的节点 ID 数组
|
|
|
|
|
|
const selectedKeys = ref([]);
|
|
|
|
|
|
|
|
|
|
|
|
// 树形配置(节点唯一标识、标签、子节点字段)
|
|
|
|
|
|
const defaultProps = {
|
|
|
|
|
|
children: "children",
|
|
|
|
|
|
label: "label",
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
watchEffect(() => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
if (!message.value) return; // 如果没有新消息,直接返回
|
|
|
|
|
|
const json = JSON.parse(message.value);
|
|
|
|
|
|
// console.info(json);
|
|
|
|
|
|
const evtType = json.type;
|
|
|
|
|
|
// if (evtType != "Pong") {
|
|
|
|
|
|
// emitter.emit("evtType", { type: evtType, data: message.value });
|
|
|
|
|
|
// }
|
|
|
|
|
|
// }
|
|
|
|
|
|
switch (evtType) {
|
|
|
|
|
|
case "ReloadLayer":
|
|
|
|
|
|
let layerData = json.data;
|
|
|
|
|
|
showLayers(layerData);
|
|
|
|
|
|
loading.value = false;
|
|
|
|
|
|
console.log("加载:", loading.value);
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
} finally {
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 组装树的数据
|
|
|
|
|
|
const showLayers = (layerData) => {
|
|
|
|
|
|
// 确保layerData是有效的JSON字符串
|
|
|
|
|
|
if (typeof layerData === "string") {
|
|
|
|
|
|
layerData = JSON.parse(layerData);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 确保转换后是数组
|
|
|
|
|
|
if (!Array.isArray(layerData)) {
|
|
|
|
|
|
console.error("Invalid layer data format - expected array");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
sourceData.value = layerData; // 假设data是树形结构数据
|
|
|
|
|
|
// 创建图层根节点
|
|
|
|
|
|
let layerNodes = [
|
|
|
|
|
|
{
|
|
|
|
|
|
id: "Layer:",
|
|
|
|
|
|
pId: "-1",
|
|
|
|
|
|
label: "图层",
|
|
|
|
|
|
open: true,
|
|
|
|
|
|
halfCheck: false,
|
|
|
|
|
|
status: 1,
|
|
|
|
|
|
icon: getNodeIcon(1), // 默认图标为可编辑
|
|
|
|
|
|
children: [],
|
|
|
|
|
|
},
|
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
|
|
layerNodes[0].children = layerData.map((node) => processNode(node));
|
|
|
|
|
|
|
|
|
|
|
|
treeData.value = layerNodes;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const setLayerStatus = (status) => {
|
|
|
|
|
|
let nodes = getSelectedNodes();
|
|
|
|
|
|
nodes = nodes.filter((node) => node.name !== "图层");
|
|
|
|
|
|
let nCount = nodes.length;
|
|
|
|
|
|
if (nCount === 0) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
let strStatus = "10";
|
|
|
|
|
|
if (status === 2) {
|
|
|
|
|
|
strStatus = "11";
|
|
|
|
|
|
} else if (status === 3) {
|
|
|
|
|
|
strStatus = "12";
|
|
|
|
|
|
}
|
|
|
|
|
|
let statusData = "";
|
|
|
|
|
|
for (let i = 0; i < nCount; i++) {
|
|
|
|
|
|
// var imgUrl = iconButtons.value[status].icon;
|
|
|
|
|
|
// nodes[i].status = status;
|
|
|
|
|
|
// treeObj.updateNode(nodes[i]);
|
|
|
|
|
|
editNodeById(treeData.value, nodes[i].id, status);
|
|
|
|
|
|
statusData += strStatus + "|Layer:\\" + nodes[i].fullPath + "\r\n";
|
|
|
|
|
|
}
|
|
|
|
|
|
send("SetLayersStatus", { layerData: statusData });
|
|
|
|
|
|
// 处理图层状态设置逻辑
|
|
|
|
|
|
console.log("设置图层状态为:", status);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const deleteLayer = () => {
|
|
|
|
|
|
let nodes = getSelectedNodes();
|
|
|
|
|
|
nodes = nodes.filter((node) => node.name !== "图层");
|
|
|
|
|
|
let nCount = nodes.length;
|
|
|
|
|
|
if (nCount === 0) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
let statusData = "";
|
|
|
|
|
|
for (let i = 0; i < nCount; i++) {
|
|
|
|
|
|
// statusData += (nodes[i].id + ",");
|
|
|
|
|
|
statusData += "Layer:\\" + nodes[i].fullPath + ",";
|
|
|
|
|
|
// treeRef.value.removeNode(nodes[i]);
|
|
|
|
|
|
removeNodeById(treeData.value, nodes[i].id);
|
|
|
|
|
|
}
|
|
|
|
|
|
send("DeleteLayers", { layers: statusData, widthChild: 1 });
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 删除指定ID的节点
|
|
|
|
|
|
const removeNodeById = (tree, id) => {
|
|
|
|
|
|
for (let i = 0; i < tree.length; i++) {
|
|
|
|
|
|
if (tree[i].id === id) {
|
|
|
|
|
|
const removedNode = tree.splice(i, 1)[0];
|
|
|
|
|
|
return { removed: true, removedNode };
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (tree[i].children && tree[i].children.length > 0) {
|
|
|
|
|
|
const result = removeNodeById(tree[i].children, id);
|
|
|
|
|
|
if (result.removed) {
|
|
|
|
|
|
return result;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return { removed: false };
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 修改节点的状态
|
|
|
|
|
|
const editNodeById = (tree, id, status) => {
|
|
|
|
|
|
for (let i = 0; i < tree.length; i++) {
|
|
|
|
|
|
if (tree[i].id === id) {
|
|
|
|
|
|
// 在这里可以修改节点的属性
|
|
|
|
|
|
tree[i].status = status;
|
|
|
|
|
|
tree[i].icon = getNodeIcon(status); // 更新图标
|
|
|
|
|
|
return true; // 找到并修改节点,返回true
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (tree[i].children && tree[i].children.length > 0) {
|
|
|
|
|
|
const found = editNodeById(tree[i].children, id, status);
|
|
|
|
|
|
if (found) {
|
|
|
|
|
|
return true; // 如果在子节点中找到并修改,返回true
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return false; // 没有找到节点,返回false
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
onMounted(() => {
|
|
|
|
|
|
// 页面加载完成后发送获取图层命令
|
|
|
|
|
|
// const isView = localStorage.getItem('isView');
|
|
|
|
|
|
// const nodeId = route.query.nodeId;
|
|
|
|
|
|
const id = route.query.id;
|
|
|
|
|
|
|
|
|
|
|
|
if (checkEmpty(id)) {
|
|
|
|
|
|
send("GetLayers");
|
|
|
|
|
|
} else {
|
|
|
|
|
|
const viewerToken = localStorage.getItem("viewerToken");
|
|
|
|
|
|
send("GetLayers",null,viewerToken);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
const getNodeIcon = (status) => {
|
|
|
|
|
|
switch (status) {
|
|
|
|
|
|
case 1:
|
|
|
|
|
|
return Edit;
|
|
|
|
|
|
case 2:
|
|
|
|
|
|
return Lock;
|
|
|
|
|
|
case 3:
|
|
|
|
|
|
return Hide;
|
|
|
|
|
|
default:
|
|
|
|
|
|
return Edit; // 默认图标
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 递归处理节点和子节点
|
|
|
|
|
|
const processNode = (node) => {
|
|
|
|
|
|
let nodeIcon = getNodeIcon(node.Status);
|
|
|
|
|
|
|
|
|
|
|
|
const treeNode = {
|
|
|
|
|
|
id: node.Id.toString(),
|
|
|
|
|
|
pId: "Layer:", // node.ParentId.toString(),
|
|
|
|
|
|
label: node.Name || "",
|
|
|
|
|
|
open: false,
|
|
|
|
|
|
icon: nodeIcon,
|
|
|
|
|
|
status: node.Status || 0,
|
|
|
|
|
|
fullPath: node.FullPath || "",
|
|
|
|
|
|
children: [],
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 如果有子节点,递归处理
|
|
|
|
|
|
if (node.Children && node.Children.length > 0) {
|
|
|
|
|
|
treeNode.children = node.Children.map((child) => {
|
|
|
|
|
|
const childNode = processNode(child);
|
|
|
|
|
|
// 确保子节点的pId指向父节点id
|
|
|
|
|
|
childNode.pId = treeNode.id;
|
|
|
|
|
|
return childNode;
|
|
|
|
|
|
});
|
|
|
|
|
|
// 有子节点时默认展开
|
|
|
|
|
|
treeNode.open = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
return treeNode;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
onBeforeUnmount(() => {
|
|
|
|
|
|
// emitter.off("ReloadLayer");
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 选中节点事件处理
|
|
|
|
|
|
const handleCheck = (currentNode, checkStatus) => {
|
|
|
|
|
|
selectedKeys.value = checkStatus.checkedKeys;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 获取选中的节点
|
|
|
|
|
|
const getSelectedNodes = () => {
|
|
|
|
|
|
// 通过 Tree 实例获取选中节点的完整数据
|
|
|
|
|
|
const selectedNodes = treeRef.value?.getCheckedNodes() || [];
|
|
|
|
|
|
return selectedNodes;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 清空选择
|
|
|
|
|
|
const clearSelection = () => {
|
|
|
|
|
|
treeRef.value?.setCheckedKeys([]);
|
|
|
|
|
|
selectedKeys.value = [];
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const handleConfirm = () => {
|
|
|
|
|
|
let nodes = getSelectedNodes();
|
|
|
|
|
|
nodes = nodes.filter((node) => node.name !== "图层");
|
|
|
|
|
|
let nCount = nodes.length;
|
|
|
|
|
|
if (nCount === 0) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
let statusData = "";
|
|
|
|
|
|
for (let i = 0; i < nCount; i++) {
|
|
|
|
|
|
// statusData += (nodes[i].id + ",");
|
|
|
|
|
|
statusData += nodes[i].fullPath + ",";
|
|
|
|
|
|
// treeRef.value.removeNode(nodes[i]);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// console.log("格式化的数据:", statusData);
|
|
|
|
|
|
|
|
|
|
|
|
emitter.emit("selectedLayer", statusData);
|
|
|
|
|
|
// 得到数据之后清空选择
|
|
|
|
|
|
clearSelection();
|
|
|
|
|
|
};
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<style scoped>
|
|
|
|
|
|
.tree-component {
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
height: 100%;
|
|
|
|
|
|
margin: 0 auto;
|
|
|
|
|
|
padding: 0;
|
|
|
|
|
|
border: 0;
|
|
|
|
|
|
background: #fff;
|
|
|
|
|
|
max-width: 240px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.tree-container {
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
height: calc(100vh - 75px);
|
|
|
|
|
|
overflow: auto;
|
|
|
|
|
|
/* background: lightblue; */
|
|
|
|
|
|
padding: 0;
|
|
|
|
|
|
vertical-align: middle;
|
|
|
|
|
|
/* background: #2c3e50; */
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.operation {
|
|
|
|
|
|
height: 40px;
|
|
|
|
|
|
vertical-align: middle;
|
|
|
|
|
|
padding-top: 5px;
|
|
|
|
|
|
padding-left: 10px;
|
|
|
|
|
|
border: 1px solid #eaeaea;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.popup-operation {
|
|
|
|
|
|
height: 40px;
|
|
|
|
|
|
vertical-align: middle;
|
|
|
|
|
|
padding-top: 10px;
|
|
|
|
|
|
padding-right: 10px;
|
|
|
|
|
|
border-top: 1px solid #eaeaea;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: row;
|
|
|
|
|
|
justify-content: flex-end;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.square-icon-button {
|
|
|
|
|
|
width: 25px;
|
|
|
|
|
|
height: 25px;
|
|
|
|
|
|
padding: 0 !important; /* 去掉内边距 */
|
|
|
|
|
|
border-radius: 4px; /* 设置圆角为4px,若要直角则设为0 */
|
|
|
|
|
|
display: inline-flex;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.square-icon-button:hover {
|
|
|
|
|
|
color: #ec0a0a; /* 鼠标悬停时的背景色 */
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.loading {
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
height: 100%;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
background: #333;
|
|
|
|
|
|
vertical-align: middle;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
padding: 0;
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
color: #3498db;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.actions {
|
|
|
|
|
|
margin-top: 15px;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
gap: 5px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.custom-tree {
|
|
|
|
|
|
/* 自定义文字大小 */
|
|
|
|
|
|
--tree-font-size: 13px;
|
|
|
|
|
|
--tree-icon-size: 13px;
|
|
|
|
|
|
/* overflow: auto; */
|
|
|
|
|
|
|
|
|
|
|
|
font-size: var(--tree-font-size);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.custom-tree .el-tree-node__content {
|
|
|
|
|
|
height: 25px !important;
|
|
|
|
|
|
transition: background-color 0.2s;
|
|
|
|
|
|
padding: 0;
|
|
|
|
|
|
border-radius: 6px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.custom-tree .el-tree-node__content:hover {
|
|
|
|
|
|
background-color: rgba(52, 152, 219, 0.1);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.custom-tree .el-tree-node__label {
|
|
|
|
|
|
/* font-weight: 300; */
|
|
|
|
|
|
color: #2c3e50;
|
|
|
|
|
|
white-space: nowrap;
|
|
|
|
|
|
margin-left: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.custom-tree .el-tree-node__expand-icon {
|
|
|
|
|
|
font-size: var(--tree-icon-size);
|
|
|
|
|
|
transition: transform 0.3s;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.custom-tree .el-tree-node__expand-icon.expanded {
|
|
|
|
|
|
transform: rotate(90deg);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.custom-tree .el-tree-node.is-current > .el-tree-node__content {
|
|
|
|
|
|
background-color: rgba(52, 152, 219, 0.15);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.custom-tree .el-tree-node.is-current > .el-tree-node__content .el-tree-node__label {
|
|
|
|
|
|
color: #2980b9;
|
|
|
|
|
|
/* font-weight: 400; */
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.icon-container {
|
|
|
|
|
|
display: inline-flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
margin-right: 2px;
|
|
|
|
|
|
width: 16px;
|
|
|
|
|
|
height: 16px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.icon-blue {
|
|
|
|
|
|
color: #3498db;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.icon-green {
|
|
|
|
|
|
color: #27ae60;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.icon-orange {
|
|
|
|
|
|
color: #e67e22;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.icon-purple {
|
|
|
|
|
|
color: #9b59b6;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.el-tree {
|
|
|
|
|
|
--el-tree-node-hover-bg-color: rgba(52, 152, 219, 0.1);
|
|
|
|
|
|
--el-tree-text-color: #2c3e50;
|
|
|
|
|
|
--el-tree-expand-icon-color: #e4d61b;
|
|
|
|
|
|
/* background: #333; */
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
}
|
|
|
|
|
|
</style>
|