| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170 |
- <template>
- <div class="tree-with-lines">
- <el-tree
- class="custom-tree"
- :data="props.treeData"
- :props="defaultProps"
- :expand-on-click-node="false"
- :default-expand-all="true"
- node-key="id"
- @node-click="handleNodeClick"
- :current-node-key="currentNodeKey"
- >
- <template #default="{ node, data }">
- <div class="custom-tree-node">
- <div class="node-content">
- <span class="node-icon">
- <el-icon v-if="data.type === 'folder'">
- <FolderOpened v-if="node.expanded" />
- <Folder v-else />
- </el-icon>
- <el-icon v-else><Document /></el-icon>
- </span>
- <span class="node-label">{{ node.label }}</span>
- </div>
- </div>
- </template>
- </el-tree>
- </div>
- </template>
- <script setup>
- const props = defineProps({
- treeData: {
- type: Array,
- },
- })
- watch(() => props.treeData, (newVal) => {
- if (newVal) {
- newTreeData.value = newVal;
- }
- });
- const emit = defineEmits(['send-nodeData']);
- const newTreeData = ref(props.treeData);
- const defaultProps = ref({
- children: 'children',
- label: 'label'
- })
- const handleNodeClick = (data, node) => {
- emit('send-nodeData', data,node);
- };
- </script>
- <style lang="scss"> /* 自定义树形控件样式 */
- .custom-tree {
- position: relative;
- /* 连接线样式 */
- .el-tree-node {
- position: relative;
- }
-
- .el-tree-node__children {
- position: relative;
- }
-
- /* 垂直连接线 */
- .el-tree-node__children::before {
- content: "";
- position: absolute;
- top: 0;
- bottom: 0;
- left: 15px;
- border-left: 1px dashed #c0c4cc;
- }
-
- /* 水平连接线 */
- .el-tree-node::before {
- content: "";
- position: absolute;
- top: 15px;
- left: 15px;
- width: 18px;
- height: 0;
- border-top: 1px dashed #c0c4cc;
- }
-
- /* 第一个节点的水平连接线调整 */
- .el-tree-node:first-child::before {
- top: 15px;
- }
-
- /* 最后一个节点的垂直连接线调整 */
- .el-tree-node:last-child::after {
- content: "";
- position: absolute;
- top: 15px;
- bottom: 0;
- left: 15px;
- width: 18px;
- border-left: 1px solid white;
- }
-
- /* 节点内容样式 */
- .custom-tree-node {
- flex: 1;
- display: flex;
- align-items: center;
- justify-content: space-between;
- font-size: 14px;
- padding-right: 8px;
- position: relative;
- }
-
- .node-content {
- display: flex;
- align-items: center;
- }
-
- .node-icon {
- margin-right: 6px;
- color: #e6a23c;
- }
-
- .node-label {
- padding: 2px 5px;
- border-radius: 3px;
- transition: background-color 0.3s;
- }
-
- .node-label:hover {
- background-color: #f0f9ff;
- }
-
- .node-actions {
- display: flex;
- gap: 8px;
- }
-
- .action-btn {
- padding: 2px 6px;
- font-size: 12px;
- border-radius: 3px;
- background-color: #f4f4f5;
- color: #606266;
- border: none;
- cursor: pointer;
- transition: all 0.3s;
- }
-
- .action-btn:hover {
- background-color: #409eff;
- color: white;
- }
-
- /* 选中的节点样式 */
- .el-tree-node.is-current > .el-tree-node__content .node-label {
- background-color: #ecf5ff;
- color: #409eff;
- }
- }
-
-
- /* 空数据提示 */
- .empty-tree {
- text-align: center;
- color: #909399;
- padding: 20px;
- }
- </style>
|